【问题标题】:Canvas animations running at the same time using both rAF and setInterval使用 rAF 和 setInterval 同时运行的画布动画
【发布时间】:2015-05-09 07:08:52
【问题描述】:

我有一个包含不同组件的动画。

  1. 一个人走路
  2. 气体充满腔室

这些组件中的每一个在单独使用时都可以很好地工作,但是当我尝试将两者结合起来时,动画根本就不起作用。

动画的当前状态,gas 正常工作。然而,这个人在视野中忽隐忽现,在某些时候他无处可寻。

【问题讨论】:

    标签: javascript html animation html5-canvas


    【解决方案1】:

    不要同时使用requestAnimationFramesetInterval...

    requestAnimationFrame (rAF) 产生更好的性能,因为它尝试将绘图与浏览器刷新周期同步。

    因此,如果将所有动画都放在 requestAnimationFrame 中,您将获得更好的性能。

    您可以使用单个 rAF 来驱动所有动画,方法是为每个动画创建一个对象(一个人对象和一个气体对象)。

    每个对象都持有:

    • 当前动画状态(足以绘制对象的信息)。

    • 此动画的频率和更新下一帧动画所需的数据

    这是一个示例,它每 167 毫秒为一个矩形设置动画,每 167 毫秒为一个圆设置动画

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    
    var actions=[];
    //
    actions.push({
      nextTime:0,
      delay:1000/60*10,
      fn:rect,
      dx:1,
      dy:1,
      x:20,
      y:20,
      options:{w:20,h:15,angle:0,fill:'skyblue'}
    });
    //
    actions.push({
      nextTime:0,
      delay:1000/60*3,
      fn:circle,
      dx:-1,
      dy:1,
      x:200,
      y:25,
      options:{r:12,fill:'lightsalmon'}
    });
    
    requestAnimationFrame(animate);
    
    var c=0;
    
    function animate(time){
    
      ctx.clearRect(0,0,cw,ch);
    
      for(var i=0;i<actions.length;i++){
        var a=actions[i];
        a.fn(a);
        if(time>a.nextTime){
          a.nextTime=time+a.delay;
          a.x+=a.dx;
          a.y+=a.dy;
        }
      }
    
      requestAnimationFrame(animate);
    
    }
    
    function rect(r){
      ctx.fillStyle=r.options.fill;
      ctx.fillRect(r.x,r.y,r.options.w,r.options.h);
    }
    
    function circle(c){
      ctx.beginPath();
      ctx.arc(c.x,c.y,c.options.r,0,Math.PI*2);
      ctx.closePath();
      ctx.fillStyle=c.options.fill;
      ctx.fill();
    }
    body{ background-color: ivory; padding:10px; }
    #canvas{border:1px solid red;}
    &lt;canvas id="canvas" width=300 height=300&gt;&lt;/canvas&gt;

    【讨论】:

      【解决方案2】:

      这里的问题是您每 200 毫秒绘制一次人,但由于requestAnimationFrame(paint); 会清除人,所以一旦浏览器准备好,画布的其余部分就会被绘制。

      解决办法: - 将你的 walker 的所有绘画材料移动到 paint() 函数中 - 将所有变量的声明从 animationFrames 移动到 dy 到 walker() 函数之外,你希望它们是全局的,而不是函数内的局部变量(因为你将在画中画人()-函数)

      【讨论】:

      • 如果我将整个 "var walker = setInterval(function(){..." 移动到绘图函数中,那么这将导致该人在屏幕上非常快速地移动,有没有办法在那个附近?
      • 是的,只将行ctx.drawImage(tileSheet, sourceX, sourceY,252,380,x,y,73,120); 移动到paint() 函数内部。将 setInterval 的东西留在原处。这样,这个人将被快速连续地一遍又一遍地重新绘制,但他只会每 200 毫秒接收一次新的坐标和 sprite-index。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-03
      • 1970-01-01
      • 2016-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-13
      相关资源
      最近更新 更多