可以将CanvasPixelArray
通过getImageData
发送到工作人员脚本,然后让工作人员脚本操纵其后台线程中的像素,最后将操纵的像素数组发回。
但是,我使用的是原生画布绘图功能,例如drawImage
。 drawImage
调用当前正在阻止UI线程。这会导致按钮重绘速度慢,单击按钮时会出现明显的延迟,这只是为了说明一些缺点。 (编辑:现在可以使用ctx.imageSmoothingEnabled = false
完成一项小改进,至少在带有webkit
前缀的WebKit上完成。)
我想使用Web Workers将绘图从主线程移动到后台线程中。但是,我似乎无法将画布和上下文发送给工作人员。
我找到了this notice on MDN:
注意:像往常一样,后台线程(包括worker)无法操纵DOM。如果后台线程采取的操作需要对DOM进行更改,则应将消息发送回创建者以执行该操作。
但我想按原样保留DOM;我只是想在canvas元素上绘制东西。这是可能的,还是Web Workers真的只允许计算而不是绘制?
(或者也许可以使用像drawImage
这样的函数来操纵CanvasPixelArray
而不是在画布上绘图?)
答案 0 :(得分:36)
[编辑〜5年后:其中一些已经开始改变,并且有新的网络平台功能实际上允许从工作者渲染到画布!有关详细信息,请参阅此博客:https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/ - 其余答案均提供2011年时代的信息;)
Web worker只能计算,不能修改DOM或进行任何调用以绘制到画布。但是就像你说的那样,你可以向网络工作者发布一个像素数组,以便在那里进行处理并将其发回。由于这是异步的,我不明白为什么会导致UI线程的任何减速,除非你故意阻止,直到web工作者响应(你不应该)。
所以你的drawImage
电话花了很长时间才会影响用户界面,这似乎很奇怪。这些天大多数画布都是硬件加速的,所以它们应该很好地跳过。我的猜测是你通过网络工作者绘制到画布像素数组每一帧,这实际上意味着你是在javascript 中渲染画布的软件。 Javascript仍然太慢了 - 即使C ++软件渲染器也很慢,这就是硬件加速很重要的原因。因此,您可以将某些内容渲染到Web worker 中的画布像素数组,然后当您将结果缓存到Image
一次时,然后根据需要将Image
绘制到画布上。那应该还是非常快。
编辑:你可能想要查看WebGL,在那里你可以编写片段着色器,它实际上是处理像素效果的小程序。它们完全在显卡上运行,因此速度非常快。
答案 1 :(得分:12)
[社区编辑:这个答案是在2011年编写并被接受的。其他技术已经出现(或者正在出现),可以让Web Workers和Canvas更好地共存;除了这个答案,读者应该知道这个页面上的所有答案。]
您无法将画布对象或画布上下文传递给工作线程,因为画布是DOM的一部分。
答案 2 :(得分:10)
您可以将ImageData
发布到Web Worker,后者将被操纵的ImageData
发送回调用者(主UI)线程。
E.g:
创建Web Worker:
this.renderer = new Worker("renderer.js");
将从画布创建的ImageData
发布到Web Worker:
var ctx = this.canvas.getContext('2d'); var imageData = ctx.createImageData(width, height); this.renderer.postMessage({ image: imageData });
在Web Worker中进行ImageData
操作并将其发布回主线程:
onmessage = function(e) { var processedImage = self.doImageProcessing(e.data.image); postMessage({ image: processedImage }); };
将操纵的ImageData
设置为主线程中的画布:
this.renderer.onmessage = function (e) { var ctx = this.canvas.getContext('2d'); ctx.putImageData(e.data.image, 0, 0); }
答案 3 :(得分:5)
有一个新的API可以执行此操作(目前仅在Firefox中支持,如果您启用了pref)。
见https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas和 https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/