We are using fabricjs Animation Easing with Sprite and it's kinda lagging. We also check other canvas project without fabricjs and they are also eating much of cpu. Is there a good way to solve this under canvas?
Disclaimer: I'm not a FabricJS Guru!
So take my analysis lightly... :-)
Why your animation might be lagging when many objects are involved
As @Blindman67 implies in his comment, FabricJS's "smart" objects are too heavy to be animated in very large quantities.
If your animations are almost-but-not-quite responsive...
You might try grouping your re-renderings to do fewer redraws during your animation cycle.
onChange
callback for anything that is animating.requestAnimationFrame
(aka rAF) callback and only re-render (with canvas.renderAll
) in this separate rAF loop.Notes:
By default, the rAF loop that FabricJS uses will try to loop at 60fps. Assigning onChange
callbacks on every animating object will almost certainly cause that animation loop to redraw at 60 frames-per-second.
Grouping causes all redrawings to be done in a single animation loop so that the re-renderings can be done at less than the overwhelming 60fps -- perhaps 30fps. This slower fps likely will not impair the animation effect but will give the CPU+GPU twice the time to do their renderings!
To help, the rAF loop comes with a timestamp argument that you can use to throttle the loop to execute code at less than 60fps.
Here's starting code for you to build upon
// animation related vars
var fps=30;
var delay=1000/fps;
var nextTime=0;
var isAnimating=true;
requestAnimationFrame(animate);
// Usage:
// * call startAnimating()
// * Set many objects to .animate
// * Optionally, when all animating objects report "onComplete"
// call stopAnimating()
function startAnimating(){
// set the isAnimating flag to start the animation loop
isAnimating=true;
}
function stopAnimating(){
isAnimating=false;
}
function animate(time){
// if we're not animating anything or if desired delay
// hasn't occurred, just request another loop and return
if(!isAnimating || time<nextTime){
requestAnimationFrame(animate);
return;
}
// set nextTime to the next elapsed time
nextTime=time+delay;
// re-render everything
canvas.renderAll();
// request another loop
requestAnimationFrame(animate);
}