2010年04月13日

HTML5のCanvasでペイントツールを作る

今回はCanvasを利用したペイントツールを作った。
Wacomペンタブレットの筆圧感知にも対応した。
筆圧感知のためにはここから使用環境にあわせたプラグインをインストールする必要がある。

lislis Painter 1.04
lislis Paint Image
Show me
/ Download zip


機能について

Tools (ツール)

Brush (ブラシ)

ペン先が平坦なブラシツール
太さを1くらいにしてペンタブレットで描くと、鉛筆っぽいタッチになる。

Air Brush (エアブラシ)

輪郭がぼやけたブラシツール
※現状では色を塗り重ねると、グラデーションに段々が出たり、ブラシの縁が微妙に黒ずんで、まるでクリームを盛りつけたようになることがある。

Syringe (スポイト)

クリックすると表示されている画像から色を取得する。
alt+clickでも同様の動作。

Eraser (消しゴム)

透明色で塗るブラシ。
Brushと同じくペン先は平坦

Fill Rect (矩形塗りつぶし)

矩形領域を選択色で塗りつぶす。

Clear Rect (矩形消去)

矩形領域を透明色で塗りつぶす。

Paint Fill (領域塗りつぶし:バケツツール)

クリックした場所と同じ色の閉領域を塗りつぶす。
Paint Fillダイアログでいくつかの設定が可能。

  • Paint By:
    塗りつぶし時の参照レイヤを設定する。
    • Integrated Layer: (デフォルト)
      全てのレイヤを重ねた状態の(見たままの)画像を参照してペイントする。
    • Current Layer:
      現在の描画先レイヤを参照してペイントする。
    • Current Layer 1 or 2...:
      指定した番号のレイヤを参照してペイントする。
  • Antialias:
    アンチエイリアスをかける。デフォルトでONになっている。
    Brushツールで描いた線はアンチエイリアスがかかっているので、これをONにしないと塗りに隙間があいてしまう。
    細い線は塗りに削られて消えてしまうので、細い線で描いた領域を塗る場合は、レイヤ1に線を描いてレイヤ2でPaint Fillすると良好な結果を得られる。
  • Threshold:
    同色範囲のしきい値。
    Brushで塗りつぶした領域は色が均等でないため、全体を塗りつぶすにはこの値を10程度まで上げる必要がある。

Layers (レイヤ)

描画先のレイヤを選択する。
眼のアイコンでレイヤーの可視/不可視切り替え。

Edit (編集)

Undo (元に戻す)

直前の描画をキャンセルして元に戻す。
ctrl+zでも同様の動作。
※Operaではデフォルトで、ctrl+zを押すと直前に閉じたタブを開き直す機能が同時に働いてしまう。

Clear All (全消去)

全てのレイヤを消去する。
Undoで元に戻すことはできないので注意。

Post Image (画像投稿)

描いた絵をギャラリーページに投稿する。
投稿後は強制的にギャラリーページに移動する。

Color (色選択)

RGBもしくはHSLで描画色を選択する。
Aは描画色の透明度を指定する。

Brush (ブラシサイズ)

ブラシサイズの指定
四角い領域をクリックするとブラシサイズを変更できる。
1,2,4,8...と書かれたボタンをクリックすることでもサイズを選択できる。
このブラシサイズはBrush, Air Brush, Eraserに適応される。


互換性

Chrome 4.1: ○
FireFox 3.6.3: ○
Opera 10.51: ○
IE 8.0: ×

IEでは全く動作しない。ExplorerCanvasがサポートしていないImageDataやtoDataURLを使うことを最初から予定していたので、現行のIEへの対応はあきらめている。
Chrome、FireFox、Operaではいずれも正常に動作する。
ただ、ブラウザによって動作の重さや画質に違いがある。Operaでは特に消しゴムツールが重い。


今回のまとめ

欲しい機能はまだまだ一杯あるが、まずは自分が絵を描くのに最低限必要な機能だけ実装した。
追加したい機能としては、、レイヤー関係の統合・追加/削除、範囲選択(マスク)、直線描画など。
色選択はカラーホイールでも選択できるようにしたい。

エアブラシの画質が汚いのはCanvasのビット深度が8ビットなので致し方ない。
RGBAをそれぞれ実数で保持する仮想キャンバスに描画して、それをCanvasのImageDataに描画する形にすれば画質は改善されるだろう。
でも今のところそこまでやるつもりはなく、うまく誤魔化す方法を思案中。

あとはサーバ側のプログラム。
描いた絵をサーバにPOSTして保存するのは簡単なので、掲示板やSNSと組み合わせれば、ちょっとしたWebサービスが出来る。


本ソフトウェアはjQueryを使用しています。


追記:
Syringeはレイヤー上の色を取る仕様だったが、非常にわかりにくいので、実際に目に見えている色を取得するように変更した。


追記:
ツールにPaint Fill(Flood Fill)を追加


追記:
UIの一部をテキストからアイコンに変更。
色選択でHSLとRGBをタブで切り替えられるようにした。
レイヤの可視/不可視アイコン追加。


追記:
投稿機能と投稿画像ギャラリーを試験的設置。
クライアント側ではCanvas.toDataURL()でPNG形式のDataURLを取得し、jQuery.post()でサーバーに送信している。
サーバ側では、POSTされたデータがPNGのDataURLであることを確認して、DBに記録している。

posted by lislis at 19:07| Comment(7) | TrackBack(0) | HTML5
この記事へのコメント
こんにちは。
凄く綺麗にアプリを作っていますね!
これって、ワコムのタブレットがないと線とかを書けないですよね?
Posted by yukoba at 2010年05月14日 19:41
ありがとうございます。

Wacomのプラグインでやっていることは、筆圧の取得と、ペン/消しゴムの判別だけなので、必須ではありません。
なので、マウスでも普通に描けます。

描線のスムージングはしていないので、マウスできれいな線を描くのは難しいですが・・・
Posted by lislis at 2010年05月15日 10:43
レス、ありがとうございます。

僕の環境では、マウスだけだと、ブラシが全然機能しません。
Chrome 5, Firefox 3.6, Safari 4
全部ダメです。長方形を書く方は全部大丈夫です。
Posted by yukoba at 2010年05月15日 21:11
ソースコードを拝見しました。

原因わかりました。
document.embeds["wacom-plugin"] が
undefined かどうかで、判定していますが、
プラグインが入っていなくても、
HTMLEmbedElement が返ってきます。

結果として、wacom.pressure が undefined なので、
タブレットが入っていないとおかしくなるようです。
Posted by yukoba at 2010年05月15日 21:30
ああああー
誠に申し訳ありませんでした。

Wacomのタブレットプラグインが入ってないと、全くペン系ツールが使えない酷いバグありのモノを公開しておりました。
先ほど問題を修正いたしましたので、現在はマウスで描けるようになっています。

yukoba様のご指摘、切に感謝いたします。
Posted by lislis at 2010年05月15日 22:08
仰る通り、プラグインがあろうとなかろうと
、HTMLEmbedElementは取得できるので判定には使えませんね。

var wacom = document.embeds["wacom-plugin"];
if(wacom)...

のようにしていたところを

if(wacom && wacom.isWacom)...

のように変更ました。
プラグインが入っていなければwacom.isWacomがundefinedになるので、これで正しく判定できるようになります。
Posted by lisllis at 2010年05月15日 22:29
こんにちわ。ありがとうございます。
僕のパソコンでもちゃんと動きました!
Posted by yukoba at 2010年05月17日 21:11
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/37076785

この記事へのトラックバック