我应该使用requestAnimationFrame淡入几个元素吗?要实现60fps动画?

时间:2016-06-19 18:45:12

标签: javascript css animation

尝试维持60 fps动画。目前,我得到了很多慢速帧的尖峰,发生在30~fps,并且我的眼睛看起来很明显。

重要编辑:丢弃旧的过时代码,添加带有解释的新代码

get

我的新代码在上面。它成功了:

  • 迭代几个元素(每个元素为 fadeIn: function(ele){ raf = window.requestAnimationFrame(function() { console.log(ele); var opacity = 0; function increase () { opacity += 0.05; if (opacity >= 1){ // complete ele.style.opacity = 1; return true; } ele.style.opacity = opacity; requestAnimationFrame(increase); } increase(); }); }, fadeInElements: function(elements, properties, speed, delay){ var raf; var ele; for (i = 0; i < properties.length; i++){ ele = elements[properties[i]]; console.log('outside loop ' + ele); instance.fadeIn(ele); } }, ),然后调用ele
  • 所以,所有元素都会淡入。
  • 但是,我希望每个&#34;淡入&#34;之间有fadeIn(ele)个延迟。 (每个触发50ms新元素

1 个答案:

答案 0 :(得分:2)

好消息是它实际上不是递归 - 它更像是超时。您提供了一个绘制框架的功能,浏览器会为您调用它。

这是一个答案,显示complete JSFiddle的摘录。它并没有尝试复制您的确切代码,而是尝试解释您需要知道的内容,以便您可以相应地调整代码。编写的代码很容易理解,因此我确信还有其他方法可以更快地完成它!

这个答案适用于顶层,这意味着我描述了JSFiddle源码的结束并向后推进。我个人认为这比从细节开始更容易理解。

  1. 你需要在某处开始动画。所以JSFiddle的最后一件事是

    window.requestAnimationFrame(eachFrame);    //start the animation
    

    这将在下一帧的时间内调用名为eachFrame()的函数,例如。在每秒60次的下一个倍数上。但它只会做一次。

  2. 您需要eachFrame()来跟踪我们在动画中的位置。

    var startTime = -1.0;  // -1 = a flag for the first frame.
    function eachFrame()
    {
      // Render this frame ------------------------
      if(startTime<0) {
        // very first frame (because of the -1.0): save the start time.
        startTime = (new Date()).getTime();
        render(0.0);
          // the parameter to render() is the time within the
          // animation.
      } else {
        // every frame after the first: subtract the saved startTime
        // to determine the current time.
        render( (new Date()).getTime() - startTime );
      }
    
      // Now we're done rendering one frame. ------
      //Start the timer to call this function again
      //when it's time for the next frame.
      window.requestAnimationFrame(eachFrame);  
    
    }; //eachFrame
    

    eachFrame()确定相对于动画开头的当前时间。 getTime()为您提供以毫秒为单位的时间。

    eachFrame()做的另一件事是再次致电window.requestAnimationFrame(eachFrame);。这不是递归。相反,eachFrame()将完成运行,然后在下一次框架出现后,浏览器将再次调用eachFrame()

  3. 您需要的最后一个功能是实际绘制框架!那是render(current time)。假设,例如,head1head2引用了您想要设置动画的两个标题元素,例如,在HTML中声明的<h1>元素。 clamp(x)函数返回x,但在0以下并且在1以下。

    function render(currTime)
    { // *** Put your rendering code here ***
      // How opaque should head1 be?  Its fade started at currTime=0.
      var opacity1 = clamp(currTime/FADE_DURATION);
        // over FADE_DURATION ms, opacity goes from 0 to 1
    
      // How opaque should head2 be?
      var opacity2 = clamp( (currTime-FADE_SPACING)/FADE_DURATION );
        // fades in, but doesn't start doing it until
        // FADE_SPACING ms have passed.
    
      // Apply the changes
      head1.style.opacity = opacity1;
      head2.style.opacity = opacity2;
    } //render
    

    render()中,您可以根据当前时间计算出不透明度。您不必担心帧之间的延迟,因为requestAnimationFrame会为我们处理这些问题。您通过抵消时间来错开转换。在此示例中,opacity1取决于currTime,而opacity2取决于currTime减去常量FADE_SPACING,因此元素2的不透明度更改将晚于元素1的不透明度变化FADE_SPACING ms。

  4. JSFiddle填写了所有细节。它动画了两个<h1>元素的不透明度,每个元素的动画开头之间有一个间距。我希望这有帮助!