Web浏览器绘制速率,页面上有多个动画

时间:2014-12-17 08:25:56

标签: javascript performance animation requestanimationframe

我们可以使用requestAnimationFrame在浏览器中绘制框架。但是,如果我们在同一页面上有多个动画会发生什么?

例如,如果我们有3个自定义标记和2个淡化效果,因为每个效果都有它自己requestAnimationFrame并不意味着我们实际上每帧画5次浏览器请求?

此外,如果我将文本滚动条FPS限制在30FPS但我的渐弱效果以45FPS运行并不意味着在1秒的时间内我们总共运行3 * 30 + 2 * 45 = 180幅画作?

是否会更好(考虑到我将页面上的所有动画限制为相同的FPS速率)让1 requestAnimationFrame绘制我的所有动画?因此,我最终每秒只能进行30-60帧绘画(取决于FPS限制)?

我只想尝试尽可能减少CPU使用率的方法。

2 个答案:

答案 0 :(得分:1)

将多个效果合并为一个requestAnimationFrame

相当容易

您使用一组javascript对象来定义每个效果的时间:

var timers=[];
timers.push({delay:50,nextFireTime:0,doFunction:doEffect1,counter:0});
timers.push({delay:500,nextFireTime:0,doFunction:doEffect2,counter:0});
timers.push({delay:5000,nextFireTime:0,doFunction:doEffect3,counter:0});

您可以使用一个requestAnimationFrame循环遍历循环并根据nextFireTime

触发每个效果
function timerLoop(currentTime){
    // request another loop
    requestAnimationFrame(timerLoop);   
    // iterate through each timer
    for(var i=0;i<timers.length;i++){
        // if this timer has reached its 
        //     next scheduled trigger time...
        if(currentTime>timers[i].nextFireTime){
            var t=timers[i];
            // ...then do this effect
            t.doFunction(t,i);
            // and reset the timer to fire again in the future
            t.nextFireTime=currentTime+t.delay;
        }
    }
}

这里的示例代码和演示:

&#13;
&#13;
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;


var timers=[];
timers.push({delay:50,nextFireTime:0,doFunction:doTimers,counter:0});
timers.push({delay:500,nextFireTime:0,doFunction:doTimers,counter:0});
timers.push({delay:5000,nextFireTime:0,doFunction:doTimers,counter:0});
//
requestAnimationFrame(timerLoop);
//
function timerLoop(currentTime){
  // request another loop
  requestAnimationFrame(timerLoop);   
  // iterate through each timer
  for(var i=0;i<timers.length;i++){
    // if this timer has reached its 
    //     next scheduled trigger time...
    if(currentTime>timers[i].nextFireTime){
      var t=timers[i];
      // ...then do this effect
      t.doFunction(t,i);
      // and reset the timer to fire again in the future
      t.nextFireTime=currentTime+t.delay;
    }
  }
}
//
function doTimers(t,i){ 
  // this demo just calls this one effect function
  // but you would call separate effect functions 
  // for your marquis & fades.
  ctx.clearRect(0,100+i*20-20,cw,20);
  ctx.fillText('Timer#'+i+' with '+t.delay+'ms delay has fired '+(++t.counter)+' times.',20,100+20*i);    
}
&#13;
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
&#13;
<canvas id="canvas" width=300 height=300></canvas>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

requestAnimationFrame引用内部浏览器机制来呈现整个网页的框架。当你说requestAnimationFrame你没有告诉它为你创造一些东西时,你要求它告诉你何时渲染下一帧,这样你就可以把你的动作连接到它。

因此,您可以根据需要多次使用requestAnimationFrame,并且只要您(您请求的)框架可用,浏览器就会自动同步您的操作。

当然,performancevise最好避免每帧多个函数调用(因为它们需要在每个帧内一个接一个地堆栈和执行),但从同步的角度来看它是完全无关紧要的。此外,你无法将任何帧或颜料加倍。