CanvasPixelArray
経由で取得したgetImageData
をワーカースクリプトに送信し、ワーカースクリプトにバックグラウンドスレッドのピクセルを操作させ、最終的に操作したピクセル配列をポストバックすることが可能です。
ただし、私はdrawImage
のようなネイティブのキャンバス描画関数を使用しています。 drawImage
呼び出しは現在、UIスレッドをブロックしています。これにより、ボタンの再描画が遅くなり、いくつかの欠点を挙げれば、ボタンをクリックしたときに顕著な遅延が発生します。 (編集:小さな改善はctx.imageSmoothingEnabled = false
、少なくともwebkit
接頭辞が付いたWebKitで)。
Webワーカーを使用して、メインスレッドからバックグラウンドスレッドに図面を移動したいと思います。しかし、私はキャンバスもコンテキストもワーカーに送信できないようです。
私は見つけました MDNに関するこの通知 :
注:通常どおり、ワーカーを含むバックグラウンドスレッドはDOMを操作できません。バックグラウンドスレッドによって実行されたアクションの結果、DOMが変更される必要がある場合は、その作業を行うためにメッセージを作成者に投稿する必要があります。
しかし、DOMはそのままにしておきたいと思います。 canvas要素に物を描きたいだけです。これは可能ですか、それともWebワーカーは本当に計算のみを許可され、描画は許可されませんか?
(または、キャンバスに描画する代わりに、drawImage
のような関数を使用してCanvasPixelArray
を操作することはおそらく可能ですか?)
[コミュニティ編集:この回答は2011年に作成および承認されました。WebワーカーとCanvasの共存を可能にする他のテクノロジーが出現(または出現)しています。読者はこれに関するすべての回答に注意する必要がありますこの回答以外のページ。]
キャンバスはDOMの一部であるため、キャンバスオブジェクトまたはキャンバスコンテキストをワーカースレッドに渡すことはできません。
[約5年後の編集:この一部は変更され始めており、Workerからキャンバスへのレンダリングを実際に可能にする新しいWebプラットフォーム機能があります!詳細については、このブログを参照してください: https://hacks.mozilla.org/2016/01/webgl-off-the-main-thread/ -残りの答えは2011年の時代に提供されます情報 ;)]
WebワーカーはDOMの計算のみが可能で、変更や、キャンバスへの描画の呼び出しはできません。しかし、あなたが言うように、ピクセルの配列をWebワーカーに投稿してそこで処理し、投稿し直すことができます。これは非同期なので、Webワーカーが応答するまで意図的にブロックしない限り(そうすべきではありません)、UIスレッドの速度が低下する理由はわかりません。
したがって、drawImage
の呼び出しに時間がかかりすぎてUIに影響しているのは奇妙に思われます。最近のほとんどのキャンバスはハードウェアアクセラレーションに対応しているため、うまくスキップできます。私の推測では、Webワーカーを介してキャンバスのピクセル配列ごとに描画しています(== --- ==)すべてのフレーム。これは、キャンバスjavascript。 Javascriptはまだこれを行うには遅すぎます-C++ソフトウェアレンダラーでさえ遅いので、ハードウェアアクセラレーションが重要です。したがって、何かをWebワーカーのキャンバスピクセル配列にレンダリングできます1回。次に、結果を取得したら、それをImage
once次に、そのImage
を好きなだけキャンバスに描画します。それはまだ本当に速いはずです。
編集:WebGLを調べて、ピクセルエフェクトを処理するほとんど効果のないプログラムであるフラグメントシェーダーを作成することができます。それらは完全にグラフィックカードで実行されるので、ばかげて高速です。
ImageData
をWebワーカーに投稿すると、操作されたImageData
が呼び出し元(メインUI)スレッドに返されます。
例えば。:
Webワーカーを作成します。
this.renderer = new Worker( "renderer.js");
キャンバスから作成したImageData
をWebワーカーに投稿します。
var ctx = this.canvas.getContext( '2d'); var imageData = ctx.createImageData(width、height); this.renderer.postMessage({image:imageData});
WebワーカーでImageData
操作を行い、メインスレッドにポストバックします。
onmessage = function(e){ var processesImage = self.doImageProcessing(e.data.image); postMessage({image:processingImage}); };
操作されたImageData
をメインスレッドのキャンバスに設定します。
this.renderer.onmessage = function(e){ var ctx = this.canvas.getContext( '2d'); ctx.putImageData(e.data.image、0、0); }
これを行うための新しいAPIがあります(現在、設定を有効にした場合にFirefoxでのみサポートされます)。
https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas および https://hacks.mozilla.org/2016/01/webgl-を参照してください。 off-the-main-thread / 。