[英]requestAnimationFrame only when needed runs the animation much faster than having requestAnimationFrame all the time
I am trying to create a "smooth" animation by "lerping" the difference between an element that follows the mouse and the mouse position.我试图通过“lerping”跟随鼠标的元素和鼠标位置之间的差异来创建一个“平滑”的动画。
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.在原始代码中,一个
requestAnimationFrame
“循环”在 JS 加载时开始,并且永不停止。 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这是原始演示: 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) (这个例子由 Jesper Landberg 提供给我,以便向我解释 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).在我的代码中,我尝试通过仅在
mousemove
事件被触发时运行requestAnimationFrame
"loop" 来优化它,并在它接近完成时停止它(几乎是因为它永远无法完成 lerping)。
My version: https://codepen.io/samuelgozi/pen/QeWzWy?editors=0010我的版本: 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.即使您降低
ease
乘数,它仍然感觉不同。
Can someone please explain to me what is going on?有人可以向我解释发生了什么吗?
The original only runs one loop.原始只运行一个循环。 and I think it's because you start a new animate every time you there is a mousemove event and then several will run at the same time so I modified your code a bit to only start a new animation until the current animation loop has stopped.
我认为这是因为每次发生 mousemove 事件时都会启动一个新动画,然后几个将同时运行,所以我稍微修改了你的代码,只启动一个新动画,直到当前动画循环停止。
let target = 0
let current = 0
let animating = false
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
if (!animating) {
animate()
animating = true
}
})
function animate() {
current += ((target - current) * ease) // This is where the magic happens
element.style.transform = `translate3d(${current}px, 0, 0)`
if (nearlyEqual(target, current)) {
animating = false
return
}
requestAnimationFrame(animate)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.