【问题标题】:Is there a way to instantiate a CanvasRenderingContext2D object without the document for use in a web worker?有没有办法在没有文档的情况下实例化 CanvasRenderingContext2D 对象以供 Web Worker 使用?
【发布时间】:2015-04-27 08:28:36
【问题描述】:

我知道该怎么做:

var buffer=document.createElement("canvas").getContext("2d");

这是我想做的:

var buffer=CanvasRenderingContext2D();

这可能吗?有没有办法在没有文档的createElement 方法的情况下创建 CanvasRenderingContext2D 对象?

我想知道的原因是因为我正在与网络工作者一起工作,我想看看我是否可以将一些绘图转移给工作者。绘图操作将保留在单独的线程中,对显示画布的最终渲染将在主文档线程中完成。我也不确定这是否可能。

如果有人对这些主题(网络工作者和绘图或实例化 CanvasRenderingContext2D 的方法)有任何信息,请告诉我!

谢谢!

编辑:

作为参考,我的项目的上下文是创建一个游戏循环。我注意到绘图几乎是我最密集的 cpu 任务,根据使用 Chrome 开发工具完成的配置文件,占用了我高达 10% 的 cpu。如果有某种方法可以在 Web Worker 上完成所有图像缓冲,然后将渲染上下文(或其他东西)传递回主文档线程以对显示画布进行最终绘制,那么这将是一个巨大的负担。主线程,它将处理输入和对requestAnimationFrame 的重复调用,它将处理对“canvas”元素的最终绘制。

现在,我不确定这是否可能,就像我之前所说的那样,但我看过很多教程说网络工作者非常适合图像编辑应用程序(尽管没有一个详细介绍)。也许这是指遍历图像中每个像素并执行 cpu 密集型过滤器功能的过滤器函数,但实际上,如果这些函数可以访问图像数据数组,那么为什么我不能访问图像在同一个 Web Worker 中的基本绘图操作?

无论如何,这就是项目的上下文:创建一个游戏循环,可以在 Web Worker 中处理缓冲图像,以便主线程可以专注于更新显示“画布”元素并收集用户输入。

【问题讨论】:

  • 如果你想画线并使用 2d 上下文方法,我不知道,但如果正在绘制图像(使用 ArrayBuffer 和 rgba),你可以使用该数组与工作人员进行通信。 ..
  • 即使你可以在worker中创建一个独立的上下文,你也无法将其传回;所以这种并行渲染似乎是不可能的。然而,大多数时候,您实际上可以使用上面提到的 ArrayBuffer 来组织任务。了解用例的细节可能会有所帮助。
  • 我添加了一些细节。我确实计划使用可传输对象或 ArrayBuffer 对象在线程之间发送而不是克隆,以便更快地共享。但是我阅读的文档非常坚定地认为网络工作者无法访问 DOM……不确定这是否意味着直接访问或无法访问,但我没有看到任何关于能够在线程之间传递元素对象的信息,所以我猜你不能。
  • 当他们说网络工作者非常适合图像编辑应用程序时,他们的意思就像 Juan Pablo 上面写的那样:你使用 ArrayBuffer 和 getImageData() 并从那里开始。但据我了解,这不是你想要的。您想在工作人员中实际使用绘图 API。根据规范,这是不可能的,我怀疑自己重新实现 Canvas(如下所述)会以任何方式帮助提高性能。 WebGL 会,但那是另一回事了。
  • @KlimLee。实际上,我试图让重新实现CanvasRenderingContext2D 听起来太可怕以至于不值得(!)。稍后在我的回答中,我确实建议采用“更常见”的方式将数据编组给工作人员进行处理。 ;-)

标签: javascript html multithreading canvas web-worker


【解决方案1】:

Web Worker 本身并不支持 DOM 对象。

所以画布的CanvasRenderingContext2D 在网络工作者内部是不可用的。

要在 Web Worker 中获取 CanvasRenderingContext2D,您必须复制其所有方法和属性(或至少与您的应用所需的方法和属性一样多)。

这显然是一项艰巨的任务。

GitHub 的Automattic Group 已经这样做了,以创建对 NodeJS 的 html5 画布支持:https://github.com/Automattic/node-canvas/tree/master/src 您可以以此为起点并将其所需部分转换为 javascript。这仍然是一项艰巨而艰巨的任务。

但是还有很多工作要做……

在重新创建所需的方法和属性并在工作线程上完成工作后,您仍必须将 CanvasRenderingContext2D 属性编组回主线程。您还必须将您的 web-worker-rendering-context 提取回主线程的像素数据编组。

我不知道有谁为此编写了代码。更常见的是:

  • 将数据从主线程编组到工作线程。
  • 使用工作器中的代码创建所需的数据。
  • 将工作线程中的数据编组回主线程。

【讨论】:

  • 我认为我无法胜任重新创建CanvasRenderingContext2D 的任务。此外,我怀疑它会像本机代码一样快。我可能只需要接受限制。
  • 是的,重新创建整个 API 可能没有用。但请记住,仅重新创建 API 的一部分通常在 Web Worker 中完成。例如,您可能希望对画布应用灰度滤镜。您可以将像素数据编组到 Web Worker,然后 Web Worker 将使用您直接在画布上使用的相同方法来操作像素数据。祝你的项目好运!
  • 谢谢,马克E。我的问题是我对网络工作者非常陌生。一旦我运行了一个,我将能够修补它。我想我将研究使用图像数据。也许这会产生一些结果。
  • 这里有一个相当不错的关于在 html canvas 中使用 web worker 的教程:htmlgoodies.com/html5/client/…
猜你喜欢
  • 1970-01-01
  • 2011-04-21
  • 1970-01-01
  • 2016-01-10
  • 2016-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-29
相关资源
最近更新 更多