繁体   English   中英

requestAnimationFrame 仅在需要时运行动画比一直使用 requestAnimationFrame 快得多

[英]requestAnimationFrame only when needed runs the animation much faster than having requestAnimationFrame all the time

我试图通过“lerping”跟随鼠标的元素和鼠标位置之间的差异来创建一个“平滑”的动画。

这仅用于演示目的,滚动事件和其他类型的动画也会出现问题。

在原始代码中,一个requestAnimationFrame “循环”在 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)
}

正如您在演示中看到的那样,在我的版本中它运行得更快,并且感觉不那么“轻松”,换句话说,效果丢失了。 即使您降低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)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM