I am trying to create a "smooth" animation by "lerping" the difference between an element that follows the mouse and the mouse position.
This is just for demo purposes, the issue happens with scrolling events and other kinds of animations too.
In the original code, a requestAnimationFrame
"loop" starts when JS is loaded, and never stops. And it feels to me like this is not the optimal way of doing it, but the animation works perfectly with this method.
Here is the original demo: https://codepen.io/ReGGae/pen/NQKENZ?editors=0010
let target = 0
let current = 0
const ease = 0.075
const element = document.querySelector('.js-lerp-me')
window.addEventListener('mousemove', (e) => {
target = e.clientX // Stores the mouse (X) positon
})
function animate() {
current += ((target - current) * ease) // This is where the magic happens
element.style.transform = `translate3d(${current}px, 0, 0)`
requestAnimationFrame(animate)
}
animate() // Runs 60 times per second
(This example kindly provided to me by Jesper Landberg in order to explain to me lerping)
In my code, I try to optimize it by running the requestAnimationFrame
"loop" only when the mousemove
event is fired and stop it when its nearly finished(nearly because it can never finish with lerping).
My version: https://codepen.io/samuelgozi/pen/QeWzWy?editors=0010
let target = 0
let current = 0
const ease = 0.075
const element = document.querySelector('.js-lerp-me')
// Checks that both numbers are within a range.
// The default range is 1 because the units passed to this are pixels,
// and with lerping the last pixel never really arrives at the target.
function nearlyEqual(a, b, targetDiff = 1) {
return Math.abs(a - b) < targetDiff;
}
window.addEventListener('mousemove', (e) => {
target = e.clientX // Stores the mouse (X) positon
animate()
})
function animate() {
current += ((target - current) * ease)
element.style.transform = `translate3d(${current}px, 0, 0)`
if (nearlyEqual(target, current)) return // If we are close enough to the target, then dont request another animation frame.
requestAnimationFrame(animate)
}
As you can see in the demos, in my version it runs much faster, and feels less "eased", in other words the effect is lost. even if you bring down the ease
multiplier down it still feels different.
Can someone please explain to me what is going on?