I have an animation which has different components.
- A man walking
- 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.
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)
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:
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>