WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

Closure Draw を更新し、カスタマイズ性を高めました

Web アプリケーションに手軽に図形描画機能を組み込むことができる Closure Library ベースの作図ウィジェット Closure Draw をアップデートしました。細かい改善点はいろいろあるのですが、最も大きいのは UI を完全にカスタマイズ可能にしたことです。ツールバーを作図ウィジェット本体から完全に分離し、まったく別の UI に差し替えることができます。また、ウィジェットを外部のスクリプトから制御するためのインターフェースも用意しました。

今回の改善で、 Web アプリケーション本体の UI に違和感のない形で Closure Draw を組み込めるようになりました。以下で仕様をご紹介しますので、ぜひご活用ください。

新しい Closure Draw のアーキテクチャ

今回の最も大きな変更点は、従来 closuredraw.Widget というひとつのコンポーネントで実装されていた部分を見直し、作図領域(closuredraw.Canvas)、ツールバー(closuredraw.Toolbar)、そして 2 つの間を取り持つコントローラ(closuredraw.Controller)の 3 つに分離したことです(下図、頑張って Closure Draw で描いてみました ^^;)。

詳しくは後述しますが、 Canvas ⇔ Controller ⇔ Toolbar のやりとりは完全に抽象化されているので、例えば UI をツールバー以外の Closure Draw の UI コンポーネントや HTML のリンク・ボタンで再実装することが簡単に行なえます。以下のデモでは、単純な button 要素でツールバーの機能を実装しています。

http://closure-draw.googlecode.com/svn/trunk/closu... (デモ)
http://code.google.com/p/closure-draw/source/brows... (HTML ソース)
http://code.google.com/p/closure-draw/source/brows... (JavaScript ソース)

また、 Canvas のみを使用して、スクリプトで直接コマンドを送ることで、さらに高度なカスタマイズも可能です。この方法なら、例えば赤の四角を描画するボタン(描画色を赤に変更し、矩形描画に変更するボタン)なんていうものも実装可能です。単にいくつかの色の四角と文字が描画できればいいというような場合には、それに合わせて UI を単純化できるわけです。

各クラスの詳細

それでは、 closuredraw.Canvas, closuredraw.Controller, closuredraw.Toolbar の各クラスについて詳細をご紹介します。 Closure Draw の基本的な使い方はすでに知っていることを前提にしているので、ご存じない方は以下のページも併せてご参照ください。

http://webos-goodies.jp/archives/introduction_to_c...

以下では説明していませんが、 closuredraw.Widget クラスも互換性のため残してあり、上記のページのコード例もそのまま動作するはずです。

closuredraw.Canvas

まずは closuredraw.Canvas から。このクラスは Closure Draw の作図領域の機能を実装したものです。 Closure Library の UI コンポーネント(goog.ui.Componentの派生クラス)なので、以下のように生成します。

var canvas = new closuredraw.Canvas(512, 512);
canvas.render(goog.dom.getElement('canvas'));

これで、 ID が "canvas" の要素(DIV 要素が無難です)に Closure Draw の作図領域を生成します。コンストラクタの引数は作図領域の幅、高さ、そして上記では指定していませんが、省略可能な goog.dom.DomHelper インスタンスです。

これだけでマウスで四角形が描画できるはずですが、ツールバーがないので編集モードや色などを切り替えることができません。それらを外部のスクリプトから制御する手段として、 execCommand() メソッドが実装されています。例えば、塗りつぶしの色を赤に変更するにはこうします。

canvas.execCommand(closuredraw.Command.SET_FILL_COLOR, '#ff0000');

execCommand() の第一引数は実行するコマンド(closuredraw.Command で定義されています)、第二引数はコマンドに応じたパラメータです。利用可能なコマンドを以下にまとめておきます。

コマンド動作パラメータ
SET_MODE編集モードの切り替えclosuredraw.Modeのメンバ
INSERT_IMAGE画像の挿入なし
SET_STROKE_WIDTH線幅の指定ピクセル数
SET_STROKE_COLOR線色の指定CSS カラー
SET_FILL_COLOR塗りつぶし色の指定CSS カラー
SET_FONT_SIZE文字サイズの指定ピクセル数
BRING_UP選択図形をひとつ手前になし
BRING_DOWN選択図形をひとつ奥になし
BRING_TO_TOP選択図形を最前面になし
BRING_TO_BOTTOM選択図形を最背面になし
COPY選択図形を複製なし
DELETE選択図形を削除なし

SET_MODE コマンドのパラメータは標準ツールバーのドロップダウンで表示できる編集モード(選択モードや四角形、楕円など)を指定する定数値で、 closuredraw.Mode で定義されています。以下に指定可能な値をまとめておきます。

定数名指定されるモード
MOVE選択・移動モード
MODIFY多角形の頂点編集モード
RECT四角形描画モード
ELLIPSE楕円描画モード
PATH多角形描画モード
TEXT文字描画モード

以下、 execCommand() メソッドの呼び出し例をいくつか示します。まずは楕円描画モードへの切り替えです。

canvas.execCommand(closuredraw.Command.SET_MODE, closuredraw.Mode.MOVE);

線幅の指定。

canvas.execCommand(closuredraw.Command.SET_STROKE_WIDTH, 4);

選択図形を最前面に移動。

canvas.execCommand(closuredraw.Command.BRING_TO_TOP);

ボタンなどがクリックされた際に上記のように execCommand() を呼び出せば、標準のツールバーに代わる独自の UI が実装できるわけです。しかし、ここでひとつ問題があります。 execCommand() でボタンの機能は実装できるものの、標準ツールバーの色選択ボタンのように状態に合わせて表示を変えることができません。その対策として、 STATUS_CHANGED イベントと queryStatus() メソッドが実装されています。例えば、現在の ID が "stroke-color" の要素の背景色に線色を反映させるには以下のようにします。

goog.events.listen(
  canvas, closuredraw.Canvas.EventType.STATUS_CHANGED,
  function(e) {
    var status = e.target.queryStatus(); // canvas.queryStatus() と同じ
    var el     = goog.dom.getElement('stroke-color');
    goog.style.setStyle(el, 'background-color', status.strokeWidth);
  });

線色などの状態が変化すると STATUS_CHANGED イベントが発行されるので、その中で queryStatus() メソッドを呼び出して状態を取得し、 UI を更新します。 queryStatus() の返り値は以下の値を格納したオブジェクトです。

メンバ名値の意味
mode現在の編集モード(closuredraw.Mode の値のいずれか)
strokeWidth線幅(ピクセル数)
strokeColor線色(CSS カラー)
fillColor塗りつぶし色(CSS カラー)
fontSizeフォントサイズ(ピクセル数)
isPath現在選択されている図形がパスなら true
isText現在選択されている図形が文字列なら true

ただし、現在の実装は手抜きなので、それっぽい操作が行われるたびに(実際には状態に変化がなくても)イベントが発行されてしまいます。もしイベント中で重い処理を行う場合は、ステータスが前回と変わっているかをチェックしてください。すいません…。

closuredraw.Controller

closuredraw.Controller は closuredraw.Canvas と標準ツールバー (closuredraw.Toolbar) の間を取り持つ役目を持つクラスです。また、 closuredraw.Toolbar 以外でも任意の UI コンポーネントや HTML のボタン系要素などを登録し、 closuredraw.Canvas の任意のコマンドと簡単に結びつけることが可能です。

closuredraw.Canvas に対して単純に標準ツールバーを結びつけるには、以下のようにします。

// 作図領域を作成
var canvas = new closuredraw.Canvas(512, 512);
canvas.render(goog.dom.getElement('canvas'));

// ツールバーを作成
var toolbar = new closuredraw.Toolbar();
toolbar.render(goog.dom.getElement('toolbar'));

// 作図領域とツールバーを結びつける
var controller = new closuredraw.Controller(canvas);
controller.addComponent(toolbar);

addComponent() で追加した UI コンポーネントが goog.ui.Component.EventType.ACTION イベントを発行すると、コントローラはその target の付随データ(getModel() で取得できるもの)から実行すべきコマンドやパラメータを割り出し、 canvas の execCommand() メソッドを呼び出します。つまり、標準のツールバーは各ボタンに適切なコマンドやパラメータを設定したオブジェクトを setModel() してあるわけです。

したがって、適切なオブジェクトを setModel() しておけば、ツールバー以外のコンポーネントも addComponent() で簡単に結びつけられます。例えば、以下は CustomButton を結びつける例です。

var button = new goog.ui.CustomButton('線色を赤にする');
button.setModel({ command: closuredraw.Command.SET_STROKE_COLOR, arg: '#ff0000' });
button.render();

controller.addComponent(button);

さらに、コンポーネントに updateClosureDrawStatus() メソッドを定義しておけば、 Canvas が STATUS_UPDATED イベントを発行した際に queryStatus() の返り値を引数にして呼び出してくれます。標準ツールバーはこれを使って線色などをツールバーに反映させています。

また、同様に HTML 要素も簡単に UI として追加できます。そのためには、要素の closuredrawcmd と closuredrawarg 属性にそれぞれコマンドとパラメータを設定しておきます。以下は編集モードを楕円モードにするボタンの例です。

<button id="ellipse-btn" closuredrawcmd="SET_MODE" closuredrawarg="ellipse">楕円モードに切り替え</button>

そして、この要素をコントローラの addElement() メソッドに渡せば、ボタンが機能するようになります。

controller.addElement(goog.dom.getElement('ellipse-btn'));

このように、 closuredraw.Controller を利用すると、 execCommand() を呼び出すボタンを簡単に実装できます。ただ、標準ツールバーのモード選択のようなドロップダウンボタンの場合はこう単純にはいきません(ACTION イベントの target がメニューアイテムではなくボタン本体になってしまうので)。そのため、コマンドやパラメータを直接指定できる closuredraw.CommandEvent も用意されています。こちらの使い方は closuredraw.Toolbar のソースをご覧ください。

closuredraw.Toolbar

closuredraw.Toolbar は、コントローラが理解できるように各ボタンを初期化する以外は、ごく標準的な Closure Library のツールバーです。上記のようにコントローラと連携する UI を実装する際の参考にしてください。

その他の変更点

UI のカスタマイズ以外にも、いくつか操作性の向上やバグフィクスを行っています。主なものを以下に挙げておきます。

  • これまでは図形の描画後に選択・移動モードに移っていたが、描画モードを維持するようになった。
  • 描画モードの状態でも図形の選択と回転・サイズ変更が可能になった(図形の移動は不可)。
  • 描画モード時、ダブルクリックで選択・移動モードに移行するようにした。
  • 図形の複製機能を追加した。
  • ツールバーの各ボタンにツールチップを表示するようにした。
  • 複雑な形の多角形でマウスクリックの判定を間違うことがあったので、修正。

ということで、より使いやすくなった Closure Draw 、ぜひお試しください!

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles