【问题标题】:HTML 5 canvas clip very costlyHTML 5 画布剪辑非常昂贵
【发布时间】:2014-02-05 06:45:49
【问题描述】:

我在使用带有 chrome 的 canvas clip() 时遇到了严重的性能问题。

I have made a test case to illustrate。

即使在这种简单的情况下,红色矩形也会闪烁,好像重绘需要花费太多时间,而 CPU 分析显示 clip() 方法占用了大约 10% 的 CPU。

在我的真实程序中,它达到 16% 并不断增加每一帧,直到画布几乎冻结浏览器..

我使用clip有什么问题吗?

谢谢你的建议,

问候。

【问题讨论】:

    标签: javascript html performance canvas clip


    【解决方案1】:

    原因

    插入beginPath(),因为rect() 添加到路径中,这与fillRect()/strokeRect() 不同。这里发生的情况是矩形的累积最终会随着时间的推移减慢剪裁速度。

    这与使用无法与显示器/屏幕刷新同步的setInterval 结合使用会使问题恶化。

    详细说明后者:

    使用setInterval()/setTimeout() 可能会导致撕裂,当绘图处于其操作的“中间”未完全完成并发生屏幕刷新时会发生这种情况。

    setInterval 只能采用整数值,您需要 16.67 毫秒来逐帧同步 (@60Hz)。即使setInterval 可以采用浮点数,它也不会将计时与监视器计时同步,因为计时器机制根本不受监控。

    要解决此问题,请始终使用requestAnimationFrame 将绘图与屏幕更新同步。这与监视器刷新直接相关,是一种比其他更底层和更高效的实现,是为此目的而设计的,因此得名。

    嵌入上述两个修复的解决方案

    见modified bin here。

    未来访问者的代码:

    function draw() {
    
      context.fillStyle = '#000';
      context.fillRect(0, 0, width, height);
      
      context.save();
      
      context.beginPath();            /// add a beginPath here
      context.rect(0, 0, 100, 100);
      context.clip();
      
      context.fillStyle = '#ff0000';
      context.fillRect(0, 0, 200, 200);
      
      context.restore();
    
      requestAnimationFrame(draw);    /// use rAF here
    }
    
    canvas.width = width;
    canvas.height = height;
    canvas.style.width = width+'px';
    canvas.style.height = height+'px';
    
    requestAnimationFrame(draw);      /// start loop
    

    PS:如果你需要停止循环,则在循环内注入一个条件来运行 rAF,即:

    if (isPlaying) requestAnimationFrame(draw);
    

    顺便说一句,不需要closePath(),因为这将由the specs 为您隐式完成。您可以根据需要添加它,但调用clip()(或fill() 等)将为您为完成此操作(规范针对浏览器实现者):

    计算剪切区域时,打开的子路径必须隐式关闭

    【讨论】:

    • 非常感谢!我没有考虑 beginPath(),您的解释非常有道理,并解释了为什么它会随着时间的推移变得越来越慢。 requestAnimationFrame 参数也非常有用,谢谢,问题解决了! :)
    • 非常感谢。我现在被这个问题困住了 2 天。我没有弄清楚剪辑是问题所在。我的应用程序每帧都变得越来越慢,直到我偶然发现这个问题,我才知道是什么原因造成的。
    • 当我将beginPath、rect、clip 添加到我的抽奖时,我遇到了类似的性能问题。我通过插入 save 和 restore 来修复它,如您的示例所示。
    猜你喜欢
    • 1970-01-01
    • 2011-11-10
    • 1970-01-01
    • 2014-10-06
    • 1970-01-01
    • 2010-10-28
    • 2021-11-27
    • 2018-06-05
    • 2014-10-06
    相关资源
    最近更新 更多