Cocoa Break Logo Top Soft Develop  脱力空間 Logo
Apple Web Badge
made by mi

概要 翻訳 ソース リンク がらくた

概要 Examples ADC Samples 3rd Parties etc CBOriginals

Grid

以下は、Mac OS X 10.4.11 上の Xcode 2.5 で説明しています。このウィジェットは、BlankWidgetで解説したことは繰り返しませんので、そちらを参照してください。

目次:
1 ウィジェット
2 ファイル構成
3 Grid.html
4 Grid.css
5 Grid.js
6 まとめ

1 ウィジェット

Grid.wdgt は、以下のようなウインドウをもつウィジェットです。

100 ピクセルごとに線が表示されています。右下にはウインドウのサイズが白色の文字で表示されています。また、サイズ変更コントロールが右下にあるのに注意してください。このウィジェットは拡大・縮小でき、それにしたがって、ガイド線が追加・除去されます。また、右下のサイズの数字を変化します。

2 ファイル構成

このサンプルのファイル構成は以下のようになります。

grid.png は、2002 × 1602 ピクセルサイズの画像です。以下はその左上のごく一部です。

このようにサイズ文字列以外のグリッドに表示されている背景は、この画像によるものだということがわかります。Info.plist の内容は BlankWidget と同じキーです。主要 HTML ファイルとして Grid.html が指定されています。

3 Grid.html

それでは、主要 HTML ファイルを見てみます(空行は除去して詰めています)。

Grid.html
<html> <head> <style type="text/css"> @import "Grid.css"; </style> <script type='text/javascript' src='Grid.js' charset='utf-8'/> </head> <body> <img src="Images/grid.png"> <!-- グリッド画像 --> <!-- bottom div は、coordinate と growbox を保持する。 mousemove ハンドラはマウスの移動にしたがってこの div を移動させる --> <div id='bottom' > <!-- グローボックス画像はウィジェットリソースとして提供される。 mousedown ハンドラはサイズ変更イベントを開始させる。 --> <img id='growbox' src='/System/Library/WidgetResources/resize.png' onmousedown='mouseDown(event);'/> <div id="coordinates">(210,220)</div> <!-- coordinate はウィジェットサイズを表示 --> </div> </body> </html>

最初に背景画像である grid.png があります。その次に、bottom という iddiv 要素があり、この div 要素内に growbox 画像と coordinates という div 要素が含まれています。画像には onmousedown イベントハンドラ mouseDown(event) が指定されています。コメントに mousemove と書かれていますが、このファイル内では指定されません。サイズ変更コントロール表示部 growbox がクリックされてマウスが移動された時だけ呼ばれるように、mouseDown() 内でイベントハンドラを追加しています。

4 Grid.css

スタイルシートを見てみましょう。

Grid.css
body { margin:0; } #bottom { position:absolute; top:208px; left:0px; right:0px; height:12px; } #growbox { position:absolute; right:2px; bottom:2px; -apple-dashboard-region: dashboard-region(control rectangle); } #coordinates { font: 9px "Helvetica"; font-weight: bold; color: white; position:absolute; right:17px; bottom:3px; }

id セレクタ growbox で、-apple-dashboard-region プロパティが設定されています。これは Dashboard に領域を定義しようとしてることを伝えます。引数の dashboard-region(control rectangle) は、ラベルと形状の順で、ラベルは領域の種類(現在 control だけ)を示し、形状は circle(円)または rectangle(長方形)を示します。ここでは長方形が指定されています。この領域は、JavaScript 等で使うというより、通常、ウィジェットが任意の場所でクリックしてドラッグしたときに移動されるのを、この領域内で防ぐために使われることが多いです。ボタンなど、クリック時に何らかの処理が必要な項目に対して設定されます。

このプロパティの引数は、上で使われた dashboard-region(label, geometry-type) の形のほかに、dashboard-region(label, geometry-type, offset-top, offset-right, offset-bottom, offset-left) のものもあります。この形は、その要素のサイズを領域のサイズに使うのではなく、指定されたオフセット値だけ内側に入った部分を定義する領域とします。

5 Grid.js

このスクリプトには、変数といくつかの関数が実装されています。まず、growbox の onmousedown イベントハンドラとして呼ばれる mouseDown(event) とその前にある変数定義を見てみます。

Grid.js > 変数指定と mouseDown
var growboxInset; // ドラッグの間、最後のマウス位置を追跡 var edgeOffset = 12; // グローボックのサムとウィジェットウインドウ端の右と下のオフセット // growbox上で最初にマウスがクリックされた時に呼ばれる function mouseDown(event) { document.addEventListener("mousemove", mouseMove, true); // 移動の追跡を開始 document.addEventListener("mouseup", mouseUp, true); // ドラッグ完了時に通知 // growboxInsetはウィジェットの右端と下端に対して実際にマウスクリックが起こった場所とを追跡する growboxInset = {x:(window.innerWidth - event.x), y:(window.innerHeight - event.y)}; event.stopPropagation(); event.preventDefault(); }

引数の event オブジェクトは、このハンドラを呼び出すことになったイベントです。まず最初にドラッグ中の移動を追跡するハンドラをドキュメントに追加し、それからドラッグ終了時のハンドラも追加しています。これらの関数の最初の引数はイベントの種類、2 番目は呼び出される関数、3 番目はキャプチャモードかどうかです。これが true なら、イベントが発生した瞬間にそのハンドラが処理できます。

ちなみに、通常のイベント処理の流れは、イベントが発生すると、そこから各要素を経由して、祖先へと伝わっていき、伝わった段階で、そこで要素にハンドラが設定されていれば、それが実行されます。これをイベントの伝播といいます。キャプチャモードでは、伝播を待たずにそのハンドラがすぐにイベントを処理します。

そして growboxInset をマウスクリックが起こった場所に初期化します。growbox ウインドウの内部幅から x 座標を、ウインドウの内部高さから y 座標を引いているのは、通常の左上から始まる値を、右下から始まる値へと変換するためです。

最後の stopPropagation() はイベントがこれ以上伝えられるのを防ぎます。preventDefault() は、イベントのキャンセルを通知します。これにより、イベントハンドラを呼び出した元が、そのイベントに対応するのを防ぎます。たとえば、通常のウェブページで、独自の動作を実装して、ブラウザの通常の動作をさせたくない場合などに使います。JavaScript の独自関数ですべてを行い、他で何らかの動作が入ってほしくない場合に呼び出します。

さて、ドラッグが継続されると、この関数で追加したイベントハンドラ指定により、マウスが移動されたときイベントハンドラ mouseMove(event) が呼び出されます。

Grid.js > 変数定義と mouseMove
var x,y; // マウスボタンが押され、マウスが移動された時に呼ばれる function mouseMove(event) { // 報告されたイベントデータが正当かどうかをチェック if((event.x == -1) && ( Math.abs( Math.abs(y-growboxInset.y) - Math.abs(event.y) ) > 2 ) ) { break; } // x と y は、イベントに関連して、ウィジェットのあるべき右下隅を追跡する x = event.x + growboxInset.x; y = event.y + growboxInset.y; if(x < 70) // 勝手に設定した最小幅 x = 70; if(y < 25) // 勝手に設定した最小高 y = 25; // coordinates div を適切に移動 document.getElementById("bottom").style.top = (y-edgeOffset); window.resizeTo(x,y); // ウイジェットのウインドウをサイズ変更 updateCoordinates(); // 右下に表示さされる coordinate を更新 event.stopPropagation(); event.preventDefault(); }

まず、イベントが正当なものかどうかをチェックして、ダメなら中止します。次に、growboxInset に保存された最初のクリック位置の右下からのサイズをマウス座標に足して、ドラッグされた幅だけ最初の位置を動かしています。このとき、ここで設定した最小幅と最小高より小さければ、その数値に変更します。これ以上は小さくなりません。

それから、bottom の id 属性をもつ要素を探し、そのスタイル top を設定することで、右下隅の div を適切に移動します。それから、ウインドウをサイズ変更させます。そして、このファイル内で定義されている updateCoordinates を呼び出すことで、右下の文字列を更新しています。最後にイベントがさらに処理されることを防ぎます。

文字列更新メソッドを見てみます。

Grid.js > updateCoordinates
// Grid 特有のコード // 現在のウィジェットサイズで coordinate の表示を更新 function updateCoordinates() { coordinates.innerText = "(" + window.innerWidth +"," + window.innerHeight + ")"; event.stopPropagation(); event.preventDefault(); }

内部テキストにサイズを示す文字列を設定しているだけです。

さて、ドラッグの最後にマウスが離されたとき、mouseDown() で追加したハンドラが呼ばれます。

Grid.js > updateCoordinates
// マウスボタンが離された後で呼ばれる function mouseUp(event) { document.removeEventListener("mousemove", mouseMove, true); // マウス追跡を停止 document.removeEventListener("mouseup", mouseUp, true); // マウスが再び離された時の通知を停止 event.stopPropagation(); event.preventDefault(); }

この関数は簡単です。単に mouseDown で追加したハンドラを除去しているだけです。これによって、マウス移動に対応するハンドラがなくなるので、マウスを移動させても拡大・縮小は起こりません。

6 まとめ

このように、ウィジェットのサイズ変更は、それほど複雑ではありません。このサンプルの JavaScript は、そのまま、または修正するなどして、独自のウィジェットでも使うことができるでしょう。


管理人:神吉 秀典 E-mail:puer@ba.wakwak.com