浮遊処理関数を定期的に呼び出す処理の実装
さて後はMoveInertiaメソッドが定期的に呼び出されるようにする必要があります。MoveInertiaメソッドの内部をみてみましょう。
1行目にif(Operation.DragingObject!=$(element))という条件分岐がありますが、ここでは常に成り立つと考えておきます。これはドラッグ処理との兼ね合いで必要な条件分岐で、詳細は後述します。
上記の条件分岐が満たされた場合、MoveInertiaメソッドはメソッドの最後の行でSetTimeoutを利用して自分自身を指定した秒数後に呼び出しています。そのため、ページがロードされた段階でこのメソッドを1度呼び出すと、MoveInertiaメソッドは指定された間隔で繰返し呼び出されることになります。
ページがロードされた段階でMoveInertiaメソッドを呼び出すためのコードをOnPreRenderメソッドに追加します。
protected override void OnPreRender(EventArgs e) { this.Style.Add("position", "absolute"); this.Style.Add("posTop", this.zVerticalPosition.ToString()); this.Style.Add("posLeft", this.zHorisontalPosition.ToString()); this.Style.Add(HtmlTextWriterStyle.Cursor, "move"); ///スクリプトへのリンク this.Page.ClientScript.RegisterClientScriptResource( typeof(JavaScript) , "Obic.Higuchi.UI.WebForm.JavaScript.Prototype.js"); this.Page.ClientScript.RegisterClientScriptResource( typeof(JavaScript) , "Obic.Higuchi.UI.WebForm.JavaScript.Operation.js"); if (this.zCanDrag == true) { ///DragStart this.Page.ClientScript.RegisterStartupScript( typeof(MovableFolder) , this.ClientID + "DragStart" , JavaScript.StartScript + "Event.observe($('" + this.ClientID + "')," + " 'mousedown', $('" + this.ClientID + "').DragStart, false);" + JavaScript.EndScript + Environment.NewLine); ///DragItem this.Page.ClientScript.RegisterStartupScript( typeof(JavaScript) , JavaScript.DragItemKey, JavaScript.StartScript + "Event.observe(document," + " 'mousemove', Operation.DragItem, false);" + JavaScript.EndScript + Environment.NewLine); ///DragEnd this.Page.ClientScript.RegisterStartupScript( typeof(JavaScript), this.ClientID + "DragEnd" , JavaScript.StartScript + "Event.observe(document," + " 'mouseup', Operation.DragEnd , false);" + JavaScript.EndScript + Environment.NewLine); } ///追加部分↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ if (this.zIsFloat == true) { ///SetDestination this.Page.ClientScript.RegisterStartupScript( typeof(MovableFolder) , this.ClientID + "SetPositionProperty" , JavaScript.StartScript + "Event.observe($('" + this.ClientID + "')," + " 'mouseup' , $('" + this.ClientID + "').SetPositionProperty , false);" + JavaScript.EndScript + Environment.NewLine); ///移動関数 this.Page.ClientScript.RegisterStartupScript( typeof(MovableFolder) , this.ClientID + "Initialize" , JavaScript.StartScript + "$('" + this.ClientID + "').SetPositionProperty();" + JavaScript.EndScript + Environment.NewLine); } ///追加部分↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ }
IsFloatがtrueのときのみ、移動処理のクライアントスクリプトが書き出されます。このコードの追加により、ページロードが完了した段階でMoveInertiaメソッドが呼び出されることとなります。
MoveInertiaメソッドの1行目の部分
if(Operation.DragingObject!=$(element))
は、ドラッグ中にこのMoveInertiaメソッドの処理を停止させるための条件分岐です。ドラッグが開始されるとこの条件分岐は偽になり、MoveInertiaメソッドの呼び出しが停止されます。
これにより、コントロールはマウスの位置に従って座標を変化させるので、ドラッグすることが可能になります。
一度停止したMoveInertiaメソッドは、ドラッグ終了の時点で再度繰返し呼び出されるようにする必要があります。そのための処理がSetPositionPropertyメソッドの最後の行に記述してあります。SetPositionPropertyメソッドでは、ドラッグしたコントロールの浮遊先の座標の修正も行っています。座標の修正を行った後MoveInertiaメソッドを呼び出すことにより、画面がスクロールした時にコントロールを浮遊させることができます。
サンプルのWebSite
作成したDLLを参照設定すれば任意のASP.NET Webアプリケーションで利用することが可能ですが、1点だけ注意する点があります。Visual Studio 2005でaspxページを作成すると、HTMLソースコードの上部に以下のタグが自動で挿入されます。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
このタグがあると、ドラッグは可能ですが浮遊処理が行われません。取り除くと浮遊処理が可能になります。
まとめ
今回はprototype.jsを利用してドラッグ可能なカスタムコントロールを作成しました。prototype.jsを応用すれば、他にもWindowsFormのようなドラッグ・リサイズが可能なコントロールや、コンテキストメニューのようなコントロールなども比較的簡単に作成することができます。
参考になれば幸いです。
参考資料
- 『プログラミング Microsoft .NET Framework MicrosoftPress』 Jeffery Richter 著、吉松史彰 訳、日経BPソフトプレス、2002年7月
- 菊池さんの工作室
- prototype.jsの使い方
