Skip to content

Commit 0934cfb

Browse files
committed
オフスクリーンキャンバスの原稿の画像を追加
1 parent d900685 commit 0934cfb

4 files changed

Lines changed: 54 additions & 15 deletions

File tree

docs/offscreencanvas.md

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
11
---
22
title: オフスクリーンキャンバス
33
author: 池田 泰延
4-
published_date: 2019-02-12
5-
modified_date: 2019-02-12
4+
published_date: 2019-02-14
5+
modified_date: 2019-02-14
66
---
77

8-
オフスクリーンキャンバスはWeb Workers(ウェブワーカーズ)を使用してWorkerスレッドで描画処理を行える機能です。負荷の高い描画処理をWorkerスレッドに移動することで、メインスレッドの負担が軽くなり、余裕ができます。これによりメインスレッドでスムーズなユーザー操作を実現できるようになり、ユーザー体験の向上が期待できます。
8+
オフスクリーンキャンバスはWeb Workers(ウェブワーカーズ)を使用してWorkerスレッドで描画処理を行える機能です。負荷の高い描画処理をWorkerスレッドに移動することで、メインスレッドの負担が軽くなり、余裕ができます。これによりメインスレッドでスムーズなユーザー操作を実現できるようになり、ユーザー体験の向上が期待できます。具体的には、`canvas`の描画処理が大きかった場合にオフスクリーンキャンバスを使うと、ボタンクリック時の反応やCSSアニメーションが滑らかになるでしょう。
99

1010
Three.jsでもオフスクリーンキャンバスを利用できます。複雑なことをしなければ難しくなく、通常のThree.jsのコードに少しの実装を追加するだけで実現できます。
1111

12-
オフスクリーンキャンバスの機能については記事「[オフスクリーンキャンバスを使ったJSのマルチスレッド描画 – スムーズなユーザー操作実現の切り札 \- ICS MEDIA](https://ics.media/entry/19043)」で詳しく解説しています。Three.jsで利用する前に一読をオススメします
12+
オフスクリーンキャンバスの機能については記事「[オフスクリーンキャンバスを使ったJSのマルチスレッド描画 – スムーズなユーザー操作実現の切り札](https://ics.media/entry/19043)」で詳しく解説しています。この解説を読み進める前に一読ください
1313

1414

15-
## 使い方
15+
## Three.jsでの使い方
1616

17-
ワーカーを利用するにあたって、メインスレッド側とワーカー側と処理を分離する必要があります。これはファイル単位で分けなければなりません。まずはメインスレッド側のコードを紹介します。HTMLに`canvas`要素を配置し、JavaScriptではワーカー側に`canvas`要素のオフスクリーン用オブジェクトを転送します。
17+
ワーカーを利用するにあたって、メインスレッド側とワーカー側と処理を分離する必要があります。これはファイル単位で分けなければなりません。まずはメインスレッド側のコードを紹介します。HTMLに`canvas`要素を配置し、JavaScriptでは`canvas`要素のオフスクリーン用オブジェクトを取得します。ワーカーインスタンスで投げてしまいます。
18+
19+
![](../imgs/osc_simple.png)
20+
21+
- [サンプルを再生する](https://ics-creative.github.io/tutorial-three/samples/osc_simple.html)
22+
- サンプルのソースコードを確認する
23+
- [メインスレッド側](../samples/osc_simple.html)
24+
- [ワーカー側](../samples/osc_simple_worker.js)
25+
26+
27+
28+
### メインスレッド側
1829

1930
```html
2031
<canvas id="myCanvas"></canvas>
@@ -31,7 +42,11 @@ const worker = new Worker('osc_simple_worker.js');
3142
worker.postMessage({ canvas: offscreenCanvas }, [offscreenCanvas]);
3243
```
3344

34-
続いて、ワーカー側の処理を解説します。ワーカー側では、Three.jsを`importScripts()`メソッドを使って読み込みます。`importScripts()`メソッドはワーカーでのみ利用できる機能です。
45+
### ワーカー側
46+
47+
ワーカー側では、Three.jsを`importScripts()`メソッドを使って読み込みます。`importScripts()`メソッドはワーカーでのみ利用できる機能です。外部のJSファイルを読み込むことができます。
48+
49+
※ES Modules形式はワーカーで利用できないため注意ください。
3550

3651
```js
3752
importScripts(
@@ -49,20 +64,31 @@ onmessage = event => {
4964
// ・・・いろいろ処理
5065
```
5166
52-
バッドノウハウですが、ひとつだけ工夫しなければ、Three.jsをワーカー側で利用できません。Three.jsは内部でCanvas要素のstyleにアクセスします。しかし、OffscreenCanvasはDOM要素ではないため、`style`属性を持ちません。Three.jsで使用する場合はランタイムエラーを避けるため、OffscreenCanvasオブジェクトに明示的に`style`プロパティを付加します。
67+
ひとつだけ工夫しなければ、Three.jsをワーカー側で利用できません。Three.jsは内部で`canvas`要素の`style`属性にアクセスします。しかし、OffscreenCanvasはDOM要素ではないため、`style`属性を持ちません。Three.jsで使用する場合はランタイムエラーを避けるため、OffscreenCanvasオブジェクトに明示的に`style`プロパティを付加します。
5368
5469
```js
5570
// Three.jsのライブラリの内部で style.width にアクセスされてしまう
5671
// 対策しないと、エラーが発生するためダミーの値を指定
5772
canvas.style = { width: 0, height: 0 };
5873
```
5974
60-
あとは普通にコードをかけばThree.jsが動きます。コードを全部みて呆気なさを感じてください。
75+
あとは普通にコードをかけばThree.jsが動きます。次のコードを見て、呆気なさを感じてください。
76+
77+
78+
## オフスクリーンキャンバスでの画像の使い方
6179
80+
オフスクリーンキャンバスで画像を使うには`ImageBitmap`オブジェクトを利用します。
6281
63-
## 画像の使い方
82+
![](../imgs/osc_imagebitmap.png)
6483
65-
オフスクリーンキャンバスで画像を使うには`ImageBitmap`を利用します。通常の`THREE.ImageLoader()`だとDOM APIの`Image`オブジェクト、つまり`img`タグが使われます。ワーカー側ではDOM APIが利用できないため、`img`タグで画像を読み込むことはできないのです。オフスクリーンキャンバスと同時期に用意された、`ImageBitmap`オブジェクトを使います。Three.jsでは`THREE.ImageBitmapLoader()`でファイルを読み込み、`ImageBitmap`インスタンスを`THREE.CanvasTexture`でテクスチャーへと変換します。あとは、適当なマテリアルにテクスチャーとして設定するだけです。
84+
- [サンプルを再生する](https://ics-creative.github.io/tutorial-three/samples/osc_imagebitmap.html)
85+
- サンプルのソースコードを確認する
86+
- [メインスレッド側](../samples/osc_imagebitmap.html)
87+
- [ワーカー側](../samples/osc_imagebitmap_worker.js)
88+
89+
90+
91+
通常の`THREE.ImageLoader()`メソッドだとDOM APIの`Image`オブジェクト、つまり`img`タグが使われます。ワーカー側ではDOM APIが利用できないため、`img`タグで画像を読み込むことはできないのです。オフスクリーンキャンバスと同時期に用意された`ImageBitmap`オブジェクトでは、DOM APIの`Image`オブジェクトを使わずに画像データを扱えます。Three.jsでは`THREE.ImageBitmapLoader()`でファイルを読み込み、`ImageBitmap`インスタンスを`THREE.CanvasTexture`でテクスチャーへと変換します。あとは、適当なマテリアルにテクスチャーとして設定するだけです。
6692
6793
```js
6894
// テクスチャーを読み込み
@@ -76,11 +102,24 @@ const texture = await new Promise(resolve => {
76102
const material = new THREE.MeshStandardMaterial({ map: texture });
77103
```
78104
79-
## リサイズの方法
105+
上記のコードではawait/asyncの構文を使っています。オフスクリーンキャンバスが動作するような新しいブラウザーのバージョンであれば、ECMAScript 2018ぐらいは動作するでしょう。
106+
107+
## オフスクリーンキャンバスでのリサイズの方法
80108
81109
通常のThree.jsのりサイズ処理は、記事「[リサイズ処理](renderer_resize.md)」を先に読んで学習しておいてください。その上で解説します。
82110
83-
オフスクリーンキャンバスからだと、メインスレッド側のりサイズを検知できません。メインスレッド側のりサイズは、メインスレッド側で検知しなけばなりません。たとえば、次のようなコードで、ワーカー側にリサイズイベントを通知します。ワーカー側では`worker.postMessage()`メソッドにより通達を受けますが、初期化なのかリサイズイベントなのか判断する手がかりが必要なため、任意の`type`プロパティーを付与しています。
111+
![](../imgs/osc_resize.png)
112+
113+
- [サンプルを再生する](https://ics-creative.github.io/tutorial-three/samples/osc_resize.html)
114+
- サンプルのソースコードを確認する
115+
- [メインスレッド側](../samples/osc_resize.html)
116+
- [ワーカー側](../samples/osc_resize_worker.js)
117+
118+
119+
120+
オフスクリーンキャンバスからだと、メインスレッド側のリサイズイベントを検知できません。メインスレッド側のリサイズイベントは、メインスレッド側で検知しなけばなりません。
121+
122+
たとえば、次のようなコードでワーカー側にリサイズイベントを通知します。ワーカー側では`worker.postMessage()`メソッドにより通達を受けますが、初期化なのかリサイズイベントなのか判断する手がかりが必要となります。引数には区別ができるように任意の`type`プロパティーを付与しています。
84123
85124
```js
86125
// 普通のキャンバスを取得
@@ -90,7 +129,7 @@ const offscreenCanvas = canvasElement.transferControlToOffscreen();
90129
const worker = new Worker('osc_resize_worker.js');
91130
worker.postMessage(
92131
{
93-
type: 'init',
132+
type: 'init', // 処理区別のために追加
94133
canvas: offscreenCanvas,
95134
width: innerWidth,
96135
height: innerHeight,
@@ -101,7 +140,7 @@ worker.postMessage(
101140

102141
window.addEventListener('resize', event => {
103142
worker.postMessage({
104-
type: 'resize',
143+
type: 'resize', // 処理区別のために追加
105144
width: innerWidth,
106145
height: innerHeight,
107146
devicePixelRatio: devicePixelRatio

imgs/osc_imagebitmap.png

157 KB
Loading

imgs/osc_resize.png

153 KB
Loading

imgs/osc_simple.png

95.6 KB
Loading

0 commit comments

Comments
 (0)