requestAnimationFrame 仅在需要时运行动画比一直使用 requestAnimationFrame 快得多
requestAnimationFrame only when needed runs the animation much faster than having requestAnimationFrame all the time
我正在尝试通过 "lerping" 跟随鼠标的元素与鼠标位置之间的差异来创建 "smooth" 动画。
这仅用于演示目的,滚动事件和其他类型的动画也会出现此问题。
原代码中,一个requestAnimationFrame
"loop"在JS加载时启动,永不停止。我觉得这不是最佳方式,但动画与此方法完美配合。
这是原始演示: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
(这个例子由 Jesper Landberg 友情提供给我,以便向我解释 lerping)
在我的代码中,我尝试仅在触发 mousemove
事件时通过 运行 和 requestAnimationFrame
"loop" 对其进行优化,并在其接近完成时停止它(几乎是因为它永远无法以 lerping 结束。
我的版本: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)
}
正如你在demo中所看到的,在我的版本中它运行得更快,并且感觉更少"eased",也就是说效果丢失了。即使你降低 ease
乘数,它仍然感觉不同。
谁能给我解释一下这是怎么回事?
原来只有运行一个循环。我认为这是因为每次有 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)
}
我正在尝试通过 "lerping" 跟随鼠标的元素与鼠标位置之间的差异来创建 "smooth" 动画。
这仅用于演示目的,滚动事件和其他类型的动画也会出现此问题。
原代码中,一个requestAnimationFrame
"loop"在JS加载时启动,永不停止。我觉得这不是最佳方式,但动画与此方法完美配合。
这是原始演示: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
(这个例子由 Jesper Landberg 友情提供给我,以便向我解释 lerping)
在我的代码中,我尝试仅在触发 mousemove
事件时通过 运行 和 requestAnimationFrame
"loop" 对其进行优化,并在其接近完成时停止它(几乎是因为它永远无法以 lerping 结束。
我的版本: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)
}
正如你在demo中所看到的,在我的版本中它运行得更快,并且感觉更少"eased",也就是说效果丢失了。即使你降低 ease
乘数,它仍然感觉不同。
谁能给我解释一下这是怎么回事?
原来只有运行一个循环。我认为这是因为每次有 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)
}