HTML5 canvas 在 Google 中闪烁 Chrome

HTML5 canvas is flickering in Google Chrome

似乎 google chrome 的更新搞砸了我的 canvas 渲染。 我有一个非常简单的代码,可以在 canvas:

上呈现图像和文本
var onDraw = function() {
  context.clearRect(0, 0, 256, 256);
  context.drawImage(image, 0, 0, 256, 256);
  context.fillText('TEST', 0, 20);
  
  requestAnimationFrame(onDraw);
};

此代码在 Chrome 上闪烁得非常厉害:https://jsfiddle.net/gp9jxn6q/(只需将鼠标移到页面上)。

我发现只有两种方法可以防止这种行为:

  1. 为整个canvas调用context.clearRect()。但在这种情况下,我不能只重绘脏矩形。
  2. 为 canvas 设置 image-rendering: pixelated。在这种情况下,所有字体看起来都很糟糕。

还能用这个做什么?

这是一个错误,自 Chromium 版本 83 开始出现得更加频繁,自 85 版以来出现得更多(因此除了 Chrome 这也会影响 Opera 和新的 Edge)。 几个月前我在 Chromium 提交了一个问题,他们目前正在修复: https://bugs.chromium.org/p/chromium/issues/detail?id=1092080

发生的情况是在 drawImage() 调用后的下一个监视器帧中将抗锯齿设置为“最近的邻居”。这会影响源和目标元素,这会影响任何 CanvasImageSource(图像、视频、canvas:https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource)。

它是随机发生的,因为它可能与设备的性能和时序有关,因为某些图形设置可以修复错误,同时它们可以在另一台设备上创建错误。

但我也有一些好消息。我想我终于找到了一个解决方法,您可以在重置抗锯齿的 drawImage() 调用之后执行:http://jsfiddle.net/u7k5qz2p/

    <div class="chromium-issue-1092080-workaround__wrapper">
        <canvas id="canvas" width="300" height="300"></canvas>
        <div class="chromium-issue-1092080-workaround__overlay"></div>
    </div>
    context.drawImage(image, 0, 0, 256, 256);
    chromiumIssue1092080WorkaroundOverlay.style.transform = `scaleX(${Math.random()})`

它所做的是在 canvas 之上叠加一个 div。在每次 drawImage() 调用更改变换样式中的 scaleX 以触发重置 canvas.

中的抗锯齿设置后