趣味でお絵描きツールをつくっていることもあって、ブラウザで動くドローイングツールの cacoo には興味があったので nucon で cacoo について聞いてきました。 結構実装についても話していたので大変参考になりました。 個人的な感想としては「あーやっぱりそうなるよねー」という感じだったのですが、すぐに忘れてしまいそうなのでここに残しておきます。 メモを元に書いているので、脳内補完が働いている部分が多分にあると思いますので、そこは注意して読んでください。
操作に関しては State パターンを使って実装している。 Undo/Redo は Command パターンを使っていて、この設計から共同編集が可能になった。
共同編集はユーザAとユーザBでコマンドをサーバに送り合い、それを共有することで実現している。 コマンドにはシーケンシャルなIDが振られていて、それをつかって競合を検知している。
- サーバには ID:99 までのコマンドが送信されている
- A と B が ID:100 のコマンドを送ってきたら先勝ち方式であとの方はキャンセルされる
- ただし、A と B の操作しているオブジェクトが別ならば競合しないため、後のほうの ID をずらす
自分がやろうとしたことが形になっていて非常に良かった。 State パターンと Command パターンは採用しようとおもっていじりはじめたところでとまってしまっていた。 共同編集の説明も非常に参考になった。
Cacoo は Flash で動作するが、はたして HTML5(というかCanvas) で単純で置き換えられるのか、というお話。 お話の中では Flash と Canvas の比較でしたので、まずはそちらから。
Flash は Vector 描画で Canvas は Raster 描画なので、Flash では拡大・縮小などに強いが Canvas ではそうではない。
作図ツールとして Vector 描画というのは重要な要素だと思う。 ただ、Canvas というのに縛られなければ SVG で十分に要件は満たせるように思える。 (現状でも SVG はわりと高速に描画出来るようになっていて、そこまで無茶な話ではないように思う)
Canvas は基本的に再描画するときに描画しているものすべて描画しなおすが、Flash はそうではない。 Canvas でも頑張って再描画範囲を限定して描画しなおすことは可能だが大変。
Canvas の再描画範囲を限定して描画しなおすというのは、たぶん大手ソーシャルゲーム会社とかではふつうに行われていて、ものによってはライブラリが勝手にやってくれたりします。 (例: tofu.js: http://ameblo.jp/ca-1pixel/entry-11605060924.html )
また、Canvasを複数重ねてうまくレイヤー化することで再描画の影響を限定することなどもできます。 (Canvasの枚数分メモリ消費することになるので、十分に注意してつかう必要はあります)
あと、この辺りはFlashでも自力でやらないといけないと思ってたから意外だった。
Flash ではドーナツ型の図形の当たり判定できちんと真ん中の空洞は判定しないようになっているが、Canvas では空洞部分も当たり判定に含まれてしまう。
isPointInPath
の話もしていたので、ヒットテストの話だと思います。
CanvasRenderingContext2D#isPointInPath
はきちんと空洞部分も判定してくれます。
http://jsfiddle.net/7Rvmx/
おそらくですが、パスを逆方向につくることでドーナツ型の図形をつくるのを失念していたのではないでしょうか?
http://www.html5.jp/canvas/ref/method/fill.html
そもそもの話になってしまうのですが、Cacoo が向いているのは SVG だと思うので、そちらとの比較を行ったほうがよかったんじゃないかなあと思いました。 あと、上記のような問題を挙げていましたが、最も大きな問題となるのはパフォーマンスだと思います。