首页 > 解决方案 > HTML5 画布在 Google Chrome 中闪烁

问题描述

似乎谷歌浏览器的更新搞砸了我的画布渲染。我有一个非常简单的代码,可以在画布上呈现图像和文本:

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

这还能做什么?

标签: javascripthtmlgoogle-chromecanvasflicker

解决方案


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

发生的情况是在 drawImage() 调用之后的下一个监视器帧中将抗锯齿设置为“最近邻”。这会影响源元素和目标元素,并且会影响任何 CanvasImageSource(图像、视频、画布: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()})`

它的作用是在画布顶部覆盖一个 div。并且在每次 drawImage() 调用更改了变换样式中的 scaleX 以触发画布中抗锯齿设置的重置。


推荐阅读