- 2008年5月19日 12:30
- ActionScript 3.0
久々の記事になります
左手の小指を負傷したため、キーボードが非常に打ちにくいです。
まあそれは置いといて
今回は、MouseEvent.CLICK イベントの制御についてメモをしようと思います。
簡単に言えば、MouseEvent.CLICKが送出されるタイミングを
ある程度こっちで決めてしまおうというものです。
左手の小指を負傷したため、キーボードが非常に打ちにくいです。
まあそれは置いといて
今回は、MouseEvent.CLICK イベントの制御についてメモをしようと思います。
簡単に言えば、MouseEvent.CLICKが送出されるタイミングを
ある程度こっちで決めてしまおうというものです。
例えばドラッグアンドドロップできるようなオブジェクトを作るとき
クリックのタイミングを少し変えたい事も多いと思います。
例えば、ドラッグを開始している時はクリック反応させず
その場でクリックしたときは別の動作をさせたい、といった具合です。
この実装をなにも考えずに書くと、以下のようなソースになります。
一見問題は無さそうですが、このままですと
ドラッグが終了した瞬間(MOUSE_UPのタイミング)に
CLICKイベントも同時に発生してしまいます。
そのため、マウスカーソルが3pixel以上動いたらクリックを発生させない
というような処理が必要になってきます。
僕が今回実装したのは、以下の3つです。
① MOUSE_DOWN時のカーソルの座標を保持しておき
② クリックイベント送出時に変化しているかを調べ
③ 3pixel以上動いていたら、その場でイベントをキャンセルする
ソース的には以下になります。
これで、カーソルが3pixel以上動いた場合、CLICKイベントがキャンセルされます。
重要な部分は、CLICKイベントのリスナのpriorityを最大にしている事と
stopImmediatePropagationメソッドです。
priorityとは、addEventListenerの第四引数のことです。
ここの数値が大きいほど、優先的に実行されます。
指定していない場合の実行順序は、addEventListenerされた順番になります。
今回は、いかなる時でも真っ先に実行してもらうために、 設定可能なpriorityの最大値である、int.MAX_VALUE を指定しています。
stopImmediatePropagationメソッドは、それ以降のイベント通知を
その場で全てキャンセルするというものです。
今回の例では、カーソル位置が3以上ずれていたらCLICKイベントは
これ以降に通知しない。という事をしています。
stopImmediatePropagationしておかないと、外部から更にaddEventListener
されていた場合、イベントが通知されてしてしまうため、キャンセルしています。
今回説明したやり方が、方法論として正しいかは別として
priorityやstopImmediatePropagationといった考え方は
覚えておいて損は無いんじゃないかなあと思ってます。
クリックのタイミングを少し変えたい事も多いと思います。
例えば、ドラッグを開始している時はクリック反応させず
その場でクリックしたときは別の動作をさせたい、といった具合です。
この実装をなにも考えずに書くと、以下のようなソースになります。
package{
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class DragObject extend MovieClip{
/* コンストラクタ. */
public function DragObject():void{
// イベントの登録.
addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDown );
addEventListener( MouseEvent.MOUSE_UP, _onMouseUp );
addEventListener( MouseEvent.MOUSE_CLICK, _onClick );
}
/* イベントリスナ. */
private function _onMouseDown( e:MouseEvent ):void{
startDrag();
}
private function _onMouseUp( e:MouseEvent ):void{
stopDrag();
}
private function _onClick( e:MouseEvent ):void{
// クリック時の処理.
}
}
}
一見問題は無さそうですが、このままですと
ドラッグが終了した瞬間(MOUSE_UPのタイミング)に
CLICKイベントも同時に発生してしまいます。
そのため、マウスカーソルが3pixel以上動いたらクリックを発生させない
というような処理が必要になってきます。
僕が今回実装したのは、以下の3つです。
① MOUSE_DOWN時のカーソルの座標を保持しておき
② クリックイベント送出時に変化しているかを調べ
③ 3pixel以上動いていたら、その場でイベントをキャンセルする
ソース的には以下になります。
package{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;
public class DragObject extend MovieClip{
private var _clickPoint:Point;
/* コンストラクタ. */
public function DragObject():void{
// イベントの登録.
addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDown );
addEventListener( MouseEvent.MOUSE_UP, _onMouseUp );
// CLICKイベントのpriorityを最大に設定.
addEventListener(
MouseEvent.MOUSE_CLICK, _onClick, false, int.MAX_VALUE );
}
/* イベントリスナ. */
private function _onMouseDown( e:MouseEvent ):void{
// クリックされた座標を保持.
_clickPoint = new Point( e.stageX, e.stageY );
startDrag();
}
private function _onMouseUp( e:MouseEvent ):void{
stopDrag();
}
private function _onClick( e:MouseEvent ):void{
// 距離を計算.
var dist:Number =
Point.distance( _clickPoint, new Point( e.stageX, e.stageY ) );
// 距離が3以上の時はイベントを止める.
if ( 3 < dist ) {
e.stopImmediatePropagation();
}else{
// クリック時の処理.
}
}
}
}
これで、カーソルが3pixel以上動いた場合、CLICKイベントがキャンセルされます。
重要な部分は、CLICKイベントのリスナのpriorityを最大にしている事と
stopImmediatePropagationメソッドです。
priorityとは、addEventListenerの第四引数のことです。
ここの数値が大きいほど、優先的に実行されます。
指定していない場合の実行順序は、addEventListenerされた順番になります。
今回は、いかなる時でも真っ先に実行してもらうために、 設定可能なpriorityの最大値である、int.MAX_VALUE を指定しています。
stopImmediatePropagationメソッドは、それ以降のイベント通知を
その場で全てキャンセルするというものです。
今回の例では、カーソル位置が3以上ずれていたらCLICKイベントは
これ以降に通知しない。という事をしています。
stopImmediatePropagationしておかないと、外部から更にaddEventListener
されていた場合、イベントが通知されてしてしまうため、キャンセルしています。
今回説明したやり方が、方法論として正しいかは別として
priorityやstopImmediatePropagationといった考え方は
覚えておいて損は無いんじゃないかなあと思ってます。
- Newer: AS3.0 addEventListenerへの無名関数渡し(のメモ)
- Older: AS3.0 16進数の色分解ではまった事