Canvas animations running at the same time using b

2019-06-14 17:02发布

问题:

I have an animation which has different components.

  1. A man walking
  2. Gas filling up a chamber

Each of these components works well when they are on their own but when i try to combine the two then the animation just doesnt work at all.

The current state of the animation, the gas works as it should. However the man flickers in and out of view and at some point he is nowhere to be seen.

回答1:

The problem here is that you're drawing the man every 200 ms, but the rest of the canvas is drawn as soon as the browser is ready, due to requestAnimationFrame(paint);, which will clear the man.

The solution this: - move all the painting stuff of your walker into the paint()-function - move the declaration of all the variables from animationFrames to dy to outside the walker()-function, you want them to be global and not local to within the function (since you'll be drawing the man in the paint()-function)



回答2:

Instead of using both requestAnimationFrame and setInterval...

requestAnimationFrame (rAF) yields better performance because it attempts to synchronize draws with browser refresh cycles.

Therefore, you get better performance if you put all your animations inside requestAnimationFrame.

You can use a single rAF to drive all your animations by creating an object for each animation (a man object and a gas object).

Each object holds:

  • the current animation status (enough information to draw the object).

  • the frequency of this animation and data needed to update the animation for the next frame

Here's an example which animates a rectangle every 167ms and a circle every

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;}
<canvas id="canvas" width=300 height=300></canvas>