使用Web Workers使用本地画布函数进行绘图
Using Web Workers for drawing using native canvas functions
可以将通过getImageData
获得的CanvasPixelArray
发送给worker脚本,并让worker脚本在其后台线程中操作像素,并最终将操作后的像素数组返回。
然而,我使用本地画布绘制功能,如drawImage
。drawImage
调用当前阻塞UI线程。这将导致按钮重绘缓慢,并且在单击按钮时出现明显的延迟,仅举几个缺点。(编辑:一个小的改进现在可以完成与ctx.imageSmoothingEnabled = false
,至少在WebKit与webkit
前缀。)
我想将绘图从主线程移动到使用Web Workers的后台线程。但是,我似乎无法将画布或上下文发送给worker。
我确实在MDN上发现了这个通知:
注意:像往常一样,后台线程——包括工作线程——不能操作DOM。如果后台线程所采取的操作需要导致DOM的更改,它们应该向其创建者发送消息以完成该工作。
但是我想让DOM保持原样;我只是想在画布元素上画东西。这是可能的吗?或者Web worker真的只允许计算而不允许绘制吗?
(或者也许可以使用像drawImage
这样的函数来操纵CanvasPixelArray
而不是在画布上绘图?)
[编辑~5年后:其中一些开始改变,并且有新的web平台功能实际上允许从Worker渲染到画布!有关更多信息,请参阅此博客:https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/-答案的其余部分提供了2011年的信息;)]
Web工作者只能计算,不能修改DOM,也不能调用绘制画布。然而,就像你说的,你可以发布一个像素数组到一个网络工作者处理它,并发布回来。因为这是异步的,我不明白为什么这会导致UI线程的任何减速,除非你故意阻塞直到web worker响应(这是你不应该的)。
所以看起来很奇怪,你的drawImage
调用花了这么长时间,它影响了UI。现在大多数画布都是硬件加速的,所以它们应该很好地跳过。我的猜测是,你是通过一个web工作者绘制画布像素数组每帧,这实际上意味着你是软件渲染画布在javascript。Javascript仍然太慢,无法做到这一点——甚至c++软件渲染器也有点慢,这就是为什么硬件加速很重要。所以你可以渲染一些东西到画布像素数组在一个web工作者一次,然后当你得到你的结果缓存到一个Image
一次,然后画的Image
到画布,你喜欢多少。那应该还是很快的。
编辑:你可能想看看WebGL,在那里你可以写片段着色器,这是有效的小程序来处理像素效果。它们完全在显卡上运行,所以速度非常快。
你可以将ImageData
发送给Web Worker,它将被操纵的ImageData
发送回调用者(主UI)线程。
例如:
-
创建Web Worker:
<>之前。 -
将从画布创建的
ImageData
发布到Web Worker:var ctx = this.canvas.getContext('2d');var imageData = ctx。createImageData(宽度、高度);this.renderer。postMessage({image: imageData});
-
在Web Worker中执行
ImageData
操作并将其发送回主线程:onmessage = function(e) {var proces沉淀物= self.doImageProcessing(.data.image);postMessage({image: processediment});};
-
在主线程中设置被操纵的
ImageData
到画布:this.renderer。Onmessage = function (e) {var ctx = this.canvas.getContext('2d');ctx.putImageData (e.data。Image, 0,0);}
有一个新的API可以做到这一点(目前只有在Firefox中启用pref时才支持)。
参见https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas和https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/。
[社区编辑:这个答案是在2011年编写并接受的。其他技术已经出现(或正在出现),它们可能会让Web Workers和Canvas更好地共存;
读者应该知道本页除了这个答案之外的所有答案。你不能将画布对象或画布上下文传递给工作线程,因为画布是DOM的一部分。
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 将函数的上下文应用于javascript变量
- 如何在JavaScript中将字符串转换为函数引用
- 用嵌套函数和默认函数定义函数
- 使用 jQuery 的 .on 函数如何获取事件的原始元素
- 无法导出函数expressjs/requestjs中的变量
- 函数参数中的数据与指定变量之间的任何性能差异
- JQuery合并了keyup和focusout两个函数
- ES6构造函数返回基类的实例
- 监视函数从服务返回不起作用,但作用域函数起作用
- 我可以在json对象中添加一个函数吗
- Canvas Html5绘图应用程序,移动画布会导致重大问题
- AngularJS:我可以跳过函数参数回调吗
- 如何使jQuery插件函数可调用以供独立使用,而不在集合上操作
- JavaScript数组排序(函数)用于对表行进行排序,而不是排序
- jqplot 使用函数返回值生成绘图
- 为什么我的 Flot 绘图函数不起作用
- 如何使html按钮调用外部javascript绘图函数
- 函数挂钩与绘图到画布等
- 使用Web Workers使用本地画布函数进行绘图