当前位置:  开发笔记 > 编程语言 > 正文

使用Web Workers使用本机canvas函数进行绘制

如何解决《使用WebWorkers使用本机canvas函数进行绘制》经验,为你挑选了4个好方法。

可以将CanvasPixelArray获取的via 发送getImageData到worker脚本,让worker脚本操纵其后台线程中的像素,最后将操作的像素阵列发回.

但是,我使用的是原生画布绘图功能drawImage.这些drawImage调用当前正在阻止UI线程.这会导致按钮重绘速度慢,单击按钮时会出现明显的延迟,这只是为了说明一些缺点.(编辑:现在可以使用ctx.imageSmoothingEnabled = false至少在带有webkit前缀的WebKit上完成一项小改进.)

我想使用Web Workers将绘图从主线程移动到后台线程中.但是,我似乎无法向工作人员发送画布和上下文.

我确实在MDN上发现了这个通知:

注意:像往常一样,后台线程(包括worker)无法操纵DOM.如果后台线程采取的操作需要导致对DOM的更改,则应将消息发送回其创建者以执行该工作.

但是我想按原样离开DOM; 我只是想在canvas元素上绘制东西.这是可能的,还是Web Workers真的只允许计算而不是绘制?

(或者也许可以使用类似drawImage操作CanvasPixelArray而不是在画布上绘制的函数?)



1> AshleysBrain..:

[编辑〜5年后:其中一些已经开始改变,并且有新的Web平台功能实际上允许从工作者渲染到画布!有关详细信息,请参阅此博客:https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/ - 其余答案均提供2011年时代信息;)]

Web工作者只能计算,而不能修改DOM或进行任何调用以绘制到画布.但是就像你说的那样,你可以向网络工作者发布一个像素数组,以便在那里进行处理并将其发回.由于这是异步的,我不明白为什么会导致UI线程的任何减速,除非你故意阻止,直到web worker响应(你不应该).

所以你的drawImage电话花了这么长时间才会影响用户界面似乎很奇怪.这些天大多数画布都是硬件加速的,所以它们应该很好地跳过.我的猜测是你每帧通过一个web worker绘制一个画布像素数组,这实际上意味着你是用javascript渲染画布的软件.Javascript仍然太慢了 - 即使C++软件渲染器也很慢,这就是硬件加速很重要的原因.所以,你可以在渲染网络工作者的东西在画布像素阵列一次,然后当你得到你的结果它缓存在一个Image 曾经,然后绘制Image到画布上,就像你喜欢.那应该还是非常快.

编辑:你可能想要查看WebGL,在那里你可以编写片段着色器,它实际上是处理像素效果的小程序.它们完全在显卡上运行,所以它们的速度非常愚蠢.



2> John Watson..:

[社区编辑:这个答案是在2011年编写并被接受的.其他技术已经出现(或正在出现),可以让Web Workers和Canvas更好地共存; 除了这个答案,读者应该知道本页面上的所有答案.]

您无法将画布对象或画布上下文传递给工作线程,因为画布是DOM的一部分.



3> Osi..:

您可以将其发布ImageData到Web Worker,后者将操纵的内容发送ImageData回调用者(主UI)线程.

例如:

    创建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 });

    ImageData操纵Web工作,并张贴回主线程:

    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);
    }


现在,如果只有某人能够创建一个`CanvasRenderingContext2D`来操作web worker上的`imageData`
@hvdd,您是否在postMessage的第二个参数中使用了[imageData]来尝试?

4> Marco..:

有一个新的API可以执行此操作(当前,只有启用了pref才受Firefox支持)。

请参阅https://developer.mozilla.org/zh-CN/docs/Web/API/OffscreenCanvas和 https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/。

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有