温馨提示:本文翻译自stackoverflow.com,查看原文请点击:fabricjs - Canvas Animation CPU issue
canvas fabricjs

fabricjs - 画布动画CPU问题

发布于 2020-04-12 09:42:26

我们正在使用带有Sprite的fabricjs动画缓动,这有点滞后。我们还检查了没有fabricjs的其他canvas项目,它们也消耗了大量的cpu。在画布下有解决此问题的好方法吗?

查看更多

提问者
Gonchar Denys
被浏览
154
markE 2016-05-16 04:35

免责声明:我不是FabricJS专家!

因此,请轻描淡写我的分析... :-)

当涉及多个对象时,为什么动画可能会滞后

正如@ Blindman67在他的评论中所暗示的那样,FabricJS的“智能”对象太重了,无法进行大量动画处理。

  • 智能==可识别事件,可代码控制(不错!)。
  • 沉重==资源密集型(不太好!)。

如果您的动画几乎没有反应,那么...

您可以尝试对重新渲染进行分组,以减少动画周期内的重新绘制次数

  • 不要onChange为动画设置任何回调。
  • 动画开始时,创建一个单独的requestAnimationFrame(又名rAF)回调,并仅canvas.renderAll在此单独的rAF循环中重新渲染(带有)。
  • 限制rAF回调循环以降低滞后的速度触发,但仍在视觉上吸引人。

笔记:

默认情况下,FabricJS使用的rAF循环将尝试以60fps循环。onChange在每个动画对象上分配回调几乎可以肯定会导致动画循环以每秒60帧的速度重绘。

分组使所有重绘都在单个动画循环中完成,因此可以以低于压倒性的60fps(也许为30fps)的速度进行重新渲染。较慢的fps可能不会削弱动画效果,但会给CPU + GPU两倍的渲染时间!

为了帮助您,rAF循环附带一个timestamp参数,您可以使用该参数来限制循环以低于60fps的速度执行代码。

这是供您构建的起始代码

// 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);
}