大変ご無沙汰しております。
ちょっとまとまった時間が取れるようになったので、lislis Painter を現行バージョンのブラウザでまともに動くように修正。
Windows 版の IE9、Chrome、Opera、FireFox、Safariでとりあえず動くようになった。
まだレイアウトが崩れている所があるので、後で手直し予定。
大変ご無沙汰しております。
ちょっとまとまった時間が取れるようになったので、lislis Painter を現行バージョンのブラウザでまともに動くように修正。
Windows 版の IE9、Chrome、Opera、FireFox、Safariでとりあえず動くようになった。
まだレイアウトが崩れている所があるので、後で手直し予定。
先日の記事で書いたように、Internet Explorer 9 Platform Preview 3で Canvas エレメントが使えるようになったので、当ブログで公開したデモの動作を確認してみた。
・ダイアログがドラッグできない。
・スライドバーも動かない。
これらjQuery uiを使っている部分のドラッグ&ドロップ系が全く動作しない模様。
いずれIEかjQueryのどちらかが改善すると思われるので対処しない。
・消しゴムをかけると真っ黒になる。
UNDOがなければ涙目レベルの不具合である。
var ctx = canvas.getContext("2d");
ctx.globalCompositeOperation = "destination-out";
と設定しても、現状の IE9 Preview が仕様通りに動作せず、無視されていることが原因。
これも時が解決することを期待して対処せず。
正常に動作する。
特に問題は見つからない。
・波が全く動かない。
さらに、画像を何度クリックしても、最初にクリックした位置に動かない波が一定時間表示されるだけという状態になる。
動作を追いかけてみると、以下のような謎な挙動が原因と判った。
特に問題はなく、きれいに表示される。
ちゃんと影が出るので、Chromeよりまともな動作と言える。
HTML5のCanvasエレメントをInternetExplorerで使うための2つのライブラリ、ExplorerCanvasとFlashCanvasの機能サポート状況を表にまとめてみた。
| ExplorerCanvas | FlashCanvas | FlashCanvas Pro | |
|---|---|---|---|
| width | ○ | ○ | ○ |
| height | ○ | ○ | ○ |
| getContext() | ○ | ○ | ○ |
| toDataURL() | × | ○ | ○ |
| ExplorerCanvas | FlashCanvas | FlashCanvas Pro | |
|---|---|---|---|
| addColorStop() | ○ | ○ | ○ |
| arc() | ○ | ○ | ○ |
| arcTo() | × | ○ | ○ |
| beginPath() | ○ | ○ | ○ |
| bezierCurveTo() | ○ | ○ | ○ |
| clip() | × | ○ | ○ |
| closePath() | ○ | ○ | ○ |
| clearRect() | △※引数を無視してCanvas全体を消去 | ○ | ○ |
| createLinearGradient() | ○ | ○ | ○ |
| createImageData() | × | × | ○ |
| createPattern() | ○ | ○ | ○ |
| drawImage() | ○ | △※ソースはimageエレメントのみ | △※ソースはimageエレメントのみ |
| fill() | ○ | ○ | ○ |
| fillRect() | ○ | ○ | ○ |
| fillStyle | ○ | ○ | ○ |
| fillText() | ※要canvas-text | × | ○ |
| font | ※要canvas-text | × | ○ |
| getImageData() | × | × | ○※遅い |
| globalAlpha | ○ | ○ | ○ |
| globalCompositeOperation | × | × | ○ |
| isPointInPath() | × | × | ○ |
| lineJoin | ○ | ○ | ○ |
| lineTo() | ○ | ○ | ○ |
| lineWidth | ○ | ○ | ○ |
| measureText() | ※要canvas-text | × | ○ |
| miterLimit | ○ | ○ | ○ |
| moveTo() | ○ | ○ | ○ |
| putImageData() | × | × | ○※遅い |
| quadraticCurveTo() | ○ | ○ | ○ |
| rect() | ○ | ○ | ○ |
| restore() | ○ | ○ | ○ |
| save() | ○ | ○ | ○ |
| scale() | ○ | ○ | ○ |
| setTransform() | ○ | ○ | ○ |
| shadowBlur | × | × | ○ |
| shadowColor | × | × | ○ |
| shadowOffsetX | × | × | ○ |
| shadowOffsetY | × | × | ○ |
| stroke() | ○ | × | ○ |
| strokeRect() | ○ | ○ | ○ |
| strokeText() | ※要canvas-text | × | ○ |
| textAlign | × | × | ○ |
| textBaseline | × | × | ○ |
| transform | ○ | ○ | ○ |
| translate() | ○ | ○ | ○ |
| ExplorerCanvas | FlashCanvas | FlashCanvas Pro | |
|---|---|---|---|
| ライセンス | オープンソース (Apache License V2.0) |
オープンソース (The MIT License) |
クローズドソース (非営利使用は無償、商用使用は有償) |
| Canvas代替技術 | VML | Flash Player 9 | Flash Player 10 (Flash Player 9 もサポート) |
これらライブラリの使用により、Canvasエレメントを使ったページがすべて無改造で動くわけではない。
サポートされていない機能が使えないのはもちろんだけど、他にも細かい動作の違いは多々ある。
特に注意が必要なのは、document.createElement("canvas")などでCanvasを動的に生成する場合だ。
ExplorerCanvasなら
var canvas = document.createElement("canvas");
document.getElementById("target").appendChild(canvas);
if (typeof initElement != "undefined") {
canvas = initElement(canvas);
}
FlashCanvasだと
var canvas = document.createElement("canvas");
document.getElementById("target").appendChild(canvas);
if (typeof FlashCanvas != "undefined") {
FlashCanvas.initElement(canvas);
}
のようにおまじないが必要になる。
このおまじないは、CanvasエレメントをdocumentのDOMツリー内にバインドしてから行う必要がある。
Canvasエレメントをどこにもappendせずに作業用のフレームバッファとして扱いたい場合は面倒だ。
lislis PainterをIE対応にできないものかと思って調べてみたけど、現状ではどちらも肝心な機能が欠けているので使えないと結論。
InternetExplorer 9のPreview版でも、Canvasをサポートしていないけど、正式版では対応してくれるといいなあ・・・
前記事のlislis Painterについての技術的説明のまとめ。
同種のプロダクトを作成する方々の参考になれば幸いだ。
現在のHTML5標準では同色塗りつぶしの機能がない。
一部ブラウザの独自実装にはあるようなので、将来的には標準化される可能性が高い。
lislis Painterではどうしているかというと、ImageDataを取得して、シードフィルアルゴリズムで塗りつぶしを行っている。
これで、Chrome、FireFox、Opera、SafariのいずれでもPaint Fillが使えるようになっている。
初めは画面全体をgetImageDataして、ペイントした後にputImageDataで描き戻せばいいと思っていたけれど、これだと問題があった。
ChromeではgetImageDataして、そのままputImageDataで描き戻すだけで、色が微妙に変わってしまうのだ。
1回では気づかないくらいの微妙な変化だけど、ペイントを繰り返すと誤差が蓄積して全く違う色になっていってしまう。
これを回避するためには、新しく透明なCanvasを作り、そこに描画して、描画レイヤにdrawImageしてやる必要がある。
将来的には不要になりそうなバッドノウハウの類だけれど、ご参考までに。
単純に同じサイズのCanvasエレメントを重ねて表示しているだけ。
レイヤを統合するときには、まず統合用のCanvasを生成して、下のレイヤから順番にdrawImageして合成する。
これは非常に簡単なやりかたで、動作も軽い。
レイヤの可視/不可視、レイヤごとの透明度指定などは簡単にできる。(未実装だけど)
反面、乗算/スクリーン/オーバーレイなどの合成モードの設定はできない。
描画した領域をgetImageDataしてImageDataをUndoバッファとして保存。
Undoするときは、新しいImageDataから順番にputImageDataでレイヤに描き戻す。
getImageData/putImageDataにはブラウザによって微妙な誤差があり、少しだけ色が変わったりぼやけたりする問題が発生する。
Undoではあまり目立たないので、この誤差には目をつぶっている。
以上、lislis Painter 1.02までの開発で、注意が要りそうだった部分を簡単にまとめた。
全般的に、Canvasの描画精度の低さには気をつけないと、どんどん誤差が蓄積して絵が荒れていくので要注意。
追記:
putImageData、drawImageの画質劣化について、Serendip様が各環境での詳細な検証をされています。
Mac版/Windows版の各ブラウザでの動作結果が掲載されており、非常に参考になります。
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |