gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

Drag and Drop 調査:fromオブジェクト変

以下、面倒なんでドラッグ&ドロップ(Drag and Drop)をDDと略します。


まず。ドラッグして移動するアイテムをfromオブジェクト、fromオブジェクトを格納する先をtoオブジェクトと仮に呼称しておきます(なんか正式名称あったら速攻切り替えますw)。
双オブジェクトとも、mx.core.UIComponentの派生クラスならOKなようです。


で…まず、仕様によらない、DDの考察を。


fromオブジェクト
・マウスをクリック(ダウン)して
・そのままの状態でマウスが移動:オブジェクトが移動する


toオブジェクト
・移動中のfromオブジェクトがtoオブジェクトの上空にいる
・その状態でマウスアップ(クリックの指を外す)が発生する
・fromオブジェクトを受け入れる準備が整ったので「かも〜ん」


こんな感じでげしょか?
とりあえず、雑に領域を用意してみましょう。fromオブジェクトにはボタンを、toオブジェクトにはパネルを用意します。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="onComplete()">

<!-- ********************************** -->
<mx:Script source="base.as" />


<!-- ********************************** -->
<mx:Panel>
	
<mx:Panel id="p1" >
</mx:Panel>

<mx:Button id="bt1" label="●" />

</mx:Panel>
	
</mx:Application>

…デザイン? なにそれおいしい?


おいといて。


では。まず「fromオブジェクトをふらふらと動かせる」ようにしてみませう。
fromオブジェクトでは、マウスをクリック(mouseDown)、マウス移動(mouseMove)のほかに。マウスのクリックで手を離してしまった時用にマウスアップ(mouseUp)のイベントを捕捉します。

private function onComplete():void{
  // マウスダウンを捕捉
  bt1.addEventListener(MouseEvent.MOUSE_DOWN, m_down);

  // マウスアップを捕捉
  bt1.addEventListener(MouseEvent.MOUSE_UP, m_up);

  // マウス移動を捕捉
  bt1.addEventListener(MouseEvent.MOUSE_MOVE, m_move);
}

// マウスダウン
private function m_down(e:MouseEvent):void{
  Alert.show("mouse_doun");
}

// マウスアップ
private function m_up(e:MouseEvent):void{
  Alert.show("mouse_up");
}

// マウス移動
private function m_move(e:MouseEvent):void{
  Alert.show("mouse_move");
}

一応動くけど…いやまぁ反応よくて面倒(苦笑
traceにしたほうが、多分試しやすいです。…moveとか凄い量になりそうだけど。


んで。イベントに反応して「実際に動かしてみたい」ので。
ちと小細工します。
動かすので、中核になるのはmoveイベント。
moveイベント内で「マウスダウンが発生したらフラグ立てて動けるようにして、マウスアップを検出したらフラグを寝かせる」ようにします…ので、先にフラグの実装から。

import flash.events.MouseEvent;

import mx.controls.Alert;


private function onComplete():void{
  // マウスダウンを捕捉
  bt1.addEventListener(MouseEvent.MOUSE_DOWN, m_down);

  // マウスアップを捕捉
  bt1.addEventListener(MouseEvent.MOUSE_UP, m_up);

  // マウス移動を捕捉
  bt1.addEventListener(MouseEvent.MOUSE_MOVE, m_move);
}

// マウスダウン
private function m_down(e:MouseEvent):void{
  this.m_flg_ = true;
}

// マウスアップ
private function m_up(e:MouseEvent):void{
  this.m_flg_ = false;
}

// マウス移動
private function m_move(e:MouseEvent):void{
  Alert.show("mouse_move");
}


//private
private var m_flg_:Boolean = false; // マウスダウンでtrueにする

で…動かすには、DragManagerという子にお願いをする必要があるようです。DragManagerのdoDrag()メソッドが必要なようなので…まずは仕様の確認。

public static function doDrag(dragInitiator:IUIComponent, dragSource:DragSource, mouseEvent:MouseEvent, dragImage:IFlexDisplayObject = null, xOffset:Number = 0, yOffset:Number = 0, imageAlpha:Number = 0.5, allowMove:Boolean = true):void

ドラッグ & ドロップ操作を開始します。
パラメータ
dragInitiator:IUIComponent ― ドラッグを開始するコンポーネントを指定する IUIComponent です。

dragSource:DragSource ― ドラッグされているデータを含む DragSource オブジェクトです。

mouseEvent:MouseEvent ― ドラッグを開始するためのマウス情報を含む MouseEvent です。

dragImage:IFlexDisplayObject (default = null) ― ドラッグするイメージ。この引数はオプションです。省略した場合、ドラッグ & ドロップ操作時には標準的なドラッグ長方形が使用されます。イメージを指定する場合は、イメージの高さと幅を明示的に設定しないとイメージが表示されません。

xOffset:Number (default = 0) ― dragImage の x オフセットをピクセル単位で指定する数値です。この引数はオプションです。これを省略すると、ドラッグプロキシはドラッグイニシエータの左上隅に表示されます。このオフセットは、ドラッグプロキシの左端からドラッグイニシエータの左端までのピクセル数として表され、通常は負の数値になります。

yOffset:Number (default = 0) ― dragImage の y オフセットをピクセル単位で指定する数値です。この引数はオプションです。これを省略すると、ドラッグプロキシはドラッグイニシエータの左上隅に表示されます。このオフセットは、ドラッグプロキシの上端からドラッグイニシエータの上端までのピクセル数として表され、通常は負の数値になります。

imageAlpha:Number (default = 0.5) ― dragImage に使用されるアルファ値を指定する数値です。この引数はオプションです。省略した場合のデフォルトのアルファ値は 0.5 です。値が 0.0 の場合、イメージは透明であることを示します。値が 1.0 の場合、イメージは完全な不透明であることを示します。

allowMove:Boolean (default = true)

まず第一パラメタはfromオブジェクトであるbt1を。
第二パラメタは…DragSource って、なんじゃらほい?

DragSource クラスには、ドラッグされるデータが格納されます。このデータには複数の形式が使用されます。たとえば、テキストコンポーネントにはプレーンテキスト、リッチテキスト、HTML データが入ります。

はぁ…つまり「移動させるブツそのものが入る」でよいのかしらん?
いくつか、余所様のサイトから、これに関連するあたりを引っかけてみる。

        var ds:DragSource = new DragSource();
        ds.addData(ddbox, "canvas");
            // DragSource オブジェクトを作成します。
            var ds:DragSource = new DragSource();
            // オブジェクトにデータを追加します。
            ds.addData(text, format);

これ↑はdragIt(event, 'red', 'color')とcallされてる。

            //ドラッグされるデータを作成
            var dragSource:DragSource = new DragSource();
            dragSource.addData(image.source, "img");

第二引数が…よぉわからん。で、調べる。

addData () メソッド
public function addData(data:Object, format:String):void

データ、および対応する形式のストリングをドラッグソースに追加します。このメソッドは値を返しません。
パラメータ
data:Object ― ドラッグデータを指定するオブジェクトです。String、DataProvider など、任意のオブジェクトを使用できます。

format:String ― このデータの形式を記述するラベルを指定するストリングです。

なるほどようはハンドル名らしい。
で…やってみた。

//
import flash.events.MouseEvent;

import mx.core.DragSource;
import mx.managers.DragManager;


private function onComplete():void{
  // マウスダウンを捕捉
  bt1.addEventListener(MouseEvent.MOUSE_DOWN, m_down);

  // マウスアップを捕捉
  bt1.addEventListener(MouseEvent.MOUSE_UP, m_up);

  // マウス移動を捕捉
  bt1.addEventListener(MouseEvent.MOUSE_MOVE, m_move);
}

// マウスダウン
private function m_down(e:MouseEvent):void{
  this.m_flg_ = true;
}

// マウスアップ
private function m_up(e:MouseEvent):void{
  this.m_flg_ = false;
}

// マウス移動
private function m_move(e:MouseEvent):void{
  if (true == this.m_flg_) {
    var ds:DragSource = new DragSource;
    ds.addData(bt1, "bt1");
    DragManager.doDrag(bt1, ds, e);
  }
}


//private
private var m_flg_:Boolean = false; // マウスダウンでtrueにする

をを動く!!


で…このままだと固定値が多くていやなので。
マウスイベントで情報取れないかなぁ…おもってたらついでに一案。マウスダウンだけで実装できね?


まず。マウスイベントは…その中にcurrentTargetってのがあるです。
っつわけで、調査。

// マウスダウン
private function m_down(e:MouseEvent):void{
trace( e.currentTarget );
trace( e.currentTarget.className );
}

DD2_0.Panel4.bt1
Button

ふむり。んでは…がりごりっとテスト実装。

// マウスダウン
private function m_down(e:MouseEvent):void{
  //DragManager.doDrag(bt1, ds, e);
  var ds:DragSource = new DragSource();
  ds.addData(e.currentTarget, "test");
  DragManager.doDrag(e.currentTarget, ds, e);
}

あれ? エラーが出る。どうやら、本当はButton型なのに「やってきたのがObject型だから僕Object型としてしか見なさないモン」と言ってるらしい…融通のきかない orz
とりあえずButtonクラスにキャストしてみる。
// マウスダウン
private function m_down(e:MouseEvent):void{
var b:Button;
b = e.currentTarget as Button;
var ds:DragSource = new DragSource();
ds.addData(e.currentTarget, "test");
DragManager.doDrag(b, ds, e);
}
無問題。で…余所で見たんだけど…DragSourceがどうもいらないくさい。実験くん。

// マウスダウン
private function m_down(e:MouseEvent):void{
  var b:Button;
  b = e.currentTarget as Button;
  DragManager.doDrag(b, new DragSource(), e);
}

よしいける!!
問題がなきゃこのままいきまっしょ。


現状のソース。


mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="onComplete()">

<!-- ********************************** -->
<mx:Script source="base.as" />


<!-- ********************************** -->
<mx:Panel>
	
<mx:Panel id="p1" >
</mx:Panel>

<mx:Button id="bt1" label="●" />

</mx:Panel>
	
</mx:Application>


Script

//
import flash.events.MouseEvent;

import mx.containers.Box;
import mx.controls.Button;
import mx.core.DragSource;
import mx.managers.DragManager;


private function onComplete():void{
  // マウスダウンを捕捉
  bt1.addEventListener(MouseEvent.MOUSE_DOWN, m_down);
}

// マウスダウン
private function m_down(e:MouseEvent):void{
  var b:Button;
  b = e.currentTarget as Button;
  DragManager.doDrag(b, new DragSource(), e);
}


//private