简体   繁体   English

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

[英]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.

相关问题 有什么比 setTimeout 和 requestAnimationFrame 更快的吗? - Is there anything faster than setTimeout and requestAnimationFrame? 使用 requestAnimationFrame 时,如何使 animation 的部分更新更快 - When using requestAnimationFrame, how to make part of animation update faster 调用requestAnimationFrame会使动画运行得更快 - Calling requestAnimationFrame causes animation to run faster 比 JavaScript 的 requestAnimationFrame 方法更好的 animation 方法? - Better animation method than requestAnimationFrame for JavaScript? Javascript基于时间的动画和requestAnimationFrame - Javascript time-based animation and requestAnimationFrame 在不同的选项卡上时,使requestAnimationFrame()动画持久存在 - Make requestAnimationFrame() Animation Persist When on Different Tab 使用鼠标坐标制作动画时的requestAnimationFrame - requestAnimationFrame when using mouse cordinates to make animation 阻止requestAnimationFrame一直运行 - Prevent requestAnimationFrame from running all the time 通过路径更改,带有requestAnimationFrame的Javascript Canvas动画变得更快 - Javascript Canvas Animation with requestAnimationFrame becomes faster by path change Javascript:使用requestAnimationFrame没有动画的代码? - Javascript: code with no animation with requestAnimationFrame?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM