【问题标题】:Modify canvas without freezing the browser (async drawing)修改画布而不冻结浏览器(异步绘图)
【发布时间】:2021-05-21 09:21:29
【问题描述】:

是否可以在不冻结浏览器的情况下在画布元素上绘图?我正在打印大约。 3.000.000 点,这会使我的浏览器冻结 2-3 秒。

谢谢!

这就是循环中发生 300 万次的情况

for (var m = 0; m <= data.length - 1; m++) {
   ....
   ctx_raw.beginPath();
   ctx_raw.fillStyle = DATA_CONFIG.color;
   ctx_raw.fillRect(x_value, y_value, 1, 1);
}

编辑 1:Chris G 的改进效率提高了 30%

const image_data = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = image_data;

var index = (x_value + y_value * canvas.width) * 4;

data[index ] = 0;
data[index + 1] = 0;
data[index + 2] = 0;
data[index + 3] = 255;

【问题讨论】:

  • 那段代码怎么叫?设置间隔?请求动画帧?还是只有一次?
  • 我更新了问题。按下按钮后调用循环
  • 这只是像素,因此您可以直接操作画布的 imageData。要异步绘制,请使用间隔并将数据分组。
  • 我很确定它比绘制单像素矩形更快,是的。真正的异步只能通过 Worker 实现,但使用间隔并在组上绘制点应该可以防止浏览器挂起。显然,以这种方式绘制所有点需要更长的时间。
  • 谢谢你,克里斯。我做了一个基准测试并绘制了像素,通过处理图像数据快了 30%!稍后我将尝试“工人”解决方案

标签: javascript asynchronous canvas


【解决方案1】:

你可以:

  1. 创建一个Worker,如果可用,它将在单独的 CPU 线程中运行,
  2. (可选)使用.postMessage()向worker发送参数,
  3. 使用OffscreenCanvas在worker内部渲染图像,
  4. 使用.getImageData()提取像素数据,
  5. 使用.postMessage()将数据发送到Window(主线程),
  6. 接收Window 上的数据并使用.putImageData() 将其渲染到&lt;canvas&gt;

另一个选择是将渲染分成几个事件循环任务。 (见How to queue a (macro)task in the JavaScript task queue?

【讨论】:

  • 非常感谢。这似乎是一个非常聪明的方法。此外,我还找到了关于“工人”的本教程。 youtube.com/watch?v=0k9erXiSp9Q
  • 为什么要从这个 OffscreenCanvas 获取图像数据?只需渲染它的占位符画布。
猜你喜欢
  • 1970-01-01
  • 2013-03-02
  • 1970-01-01
  • 1970-01-01
  • 2016-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
相关资源
最近更新 更多