JavaScript プログラミング講座

 

ドラッグアンドドロップについて

 


■ドラッグアンドドロップについて

 
ブラウザ と OS 間で、データをやり取りする事ができます。
 
DragEvent と、DataTransfer クラスを使用します。
 
原始的な機能は、Internet Explorer 6 でも利用可能です。
 
HTML5 にて標準化されました。
 
■DragEvent について
 
ドラッグやドロップ操作時に発生するイベントです。
 
このページでは、主に DragEvent について解説しています。
 
■DataTransfer クラスについて
 
「データを格納する入れ物」として使用します。
 
DataTransfer については、こちらで解説しています。
 

■データフォーマットについて

 
■転送可能なデータフォーマットについて
 
データのタイプは、以下の種類があります。
 
文字列
リンク
HTML 文字列(HTML5 世代)
ファイル(HTML5 世代)
 
■ファイルアクセスについて
 
ユーザーが任意のファイルをドロップした場合、そのファイルへアクセスが可能になります。
 
 

 

デフォルトのドラッグを無効化する

 


■デフォルトのドラッグ機能について

 
一部の要素には、専用のドラッグ機能が存在します。
 
ドラッグ操作により、データの転送準備が開始されます。
 
■ <IMG> 要素の場合
 
画像の上にマウスカーソルを重ねて、ドラッグ操作を行います。
 
すると、src プロパティ値のコピーが発生します。
 
■ <A> 要素の場合
 
アンカーの上にマウスカーソルを重ねて、ドラッグ操作を行います。
 
すると、href プロパティ値のコピーが発生します。
 
■選択済みテキストの場合
 
まず、テキストを囲んで、選択状態にします。
 
「選択済みテキスト」の上にマウスカーソルを重ねて、ドラッグ操作を行います。
 
すると、選択された文字列のコピーが発生します。
 
 

■ドラッグ操作を開始したか調べる

 
■ドラッグ操作を開始したか監視する
 
ondragstart イベントを使用します。
 
登録したコールバック関数の引数から、DragEvent オブジェクトが得られます。
 
■任意のエレメントにリスナーを登録した場合
 
検出範囲は、任意の要素とその子孫に限定されます。
 
■使用例
 
ドラッグ操作を開始したか調べる

<html>
  <body>

    <a id="aaa" href="http://example.com" >このリンクをドラッグ!!</a>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "aaa" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("aaa");

	// ------------------------------------------------------------
	// ドラッグ操作を開始した時に実行されるイベント
	// ------------------------------------------------------------
	element.ondragstart = function (e){

		console.log("ドラッグ操作を開始した");

	};

    //-->
    </script>

  </body>
</html>
 

■デフォルトのドラッグ機能を無効化する

 
■デフォルトのドラッグ機能を無効化する
 
preventDefault() メソッドを使用します。
 
 
■使用例
 
デフォルトのドラッグ機能を無効化する

<html>
  <body>

    <a id="aaa" href="http://example.com" >このリンクをドラッグ!!</a>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "aaa" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("aaa");

	// ------------------------------------------------------------
	// ドラッグ開始時に実行される関数
	// ------------------------------------------------------------
	function DragStartFunc(e){
		if(!e) e = window.event; // レガシー

		// ------------------------------------------------------------
		// デフォルトのドラッグ機能を無効化する
		// ------------------------------------------------------------
		if(e.preventDefault){
			// デフォルトの動作を無効化する
			e.preventDefault();
		}else{
			// デフォルトの動作を無効化する(非標準)
			return false;
		}
	}
	
	// ------------------------------------------------------------
	// リッスンを開始する
	// ------------------------------------------------------------
	// イベントリスナーに対応している
	if(element.addEventListener){

		element.addEventListener("dragstart" , DragStartFunc);

	// アタッチイベントに対応している
	}else if(element.attachEvent){

		element.attachEvent("ondragstart" , DragStartFunc);

	// イベントハンドラを使用する
	}else{
		element.ondragstart = DragStartFunc;
	}
    //-->
    </script>

  </body>
</html>
 
 

 

デフォルトのドロップを無効化する

 


■デフォルトのドロップ機能について

 
一部の要素には、専用のドロップ機能が存在します。
 
ドロップ操作により、データの受け取りが発生します。
 
■ <INPUT> <TEXTAREA> 要素の場合
 
データをドラッグして、コントロール要素の上で、ドロップ操作を行います。
 
すると、テキストとして貼り付ける事ができます。
 
 
■ URI 文字列を受け取った場合
 
URI 文字列を受け取ると、画面遷移が発生します。
 

■ドロップ操作が行われたか調べる

 
■ドロップ操作を監視する(データを受け取る直前)
 
ondrop イベントを使用します。
 
登録したコールバック関数の引数から、DragEvent オブジェクトが得られます。
 
■任意のエレメントにリスナーを登録した場合
 
検出範囲は、任意の要素とその子孫に限定されます。
 
■使用例
 
ドロップ操作を監視する

<html>
  <body>

    <input id="bbb" type="text" style="font-size:32px;" >

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "bbb" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("bbb");

	// ------------------------------------------------------------
	// ドロップ時に実行されるイベント(データを受け取る直前)
	// ------------------------------------------------------------
	element.ondrop = function (e){

		console.log("ドロップ操作を行った");

	};

    //-->
    </script>

  </body>
</html>
 

■デフォルトのドロップ機能を無効化する

 
■デフォルトのドロップ機能を無効化する
 
preventDefault() メソッドを使用します。
 
 
■使用例
 
デフォルトのドロップ機能を無効化する

<html>
  <body>

    <input id="bbb" type="text" style="font-size:32px;" >

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "bbb" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("bbb");

	// ------------------------------------------------------------
	// ドロップ時に実行される関数(データを受け取る直前)
	// ------------------------------------------------------------
	function DropFunc(e){
		if(!e) e = window.event; // レガシー

		// ------------------------------------------------------------
		// デフォルトのドロップ機能を無効化する
		// ------------------------------------------------------------
		if(e.preventDefault){
			// デフォルトの動作を無効化する
			e.preventDefault();
		}else{
			// デフォルトの動作を無効化する(非標準)
			return false;
		}
	}
	
	// ------------------------------------------------------------
	// リッスンを開始する
	// ------------------------------------------------------------
	// イベントリスナーに対応している
	if(element.addEventListener){

		element.addEventListener("drop" , DropFunc);

	// アタッチイベントに対応している
	}else if(element.attachEvent){

		element.attachEvent("ondrop" , DropFunc);

	// イベントハンドラを使用する
	}else{
		element.ondrop = DropFunc;
	}
    //-->
    </script>

  </body>
</html>
 
 

 

データのドラッグを開始する

 
 
 


データのドラッグを開始する

 
1.任意のエレメントのドラッグ操作を有効にする
 
draggable 属性を使用します。
 
これにより、ondragstart イベントが、確実に発行されるようになります。
 
2.ドラッグ操作を開始したか監視する
 
ondragstart イベントを使用します。
 
登録したコールバック関数の引数から、DragEvent オブジェクトが得られます。
 
3.転送データを指定する
 
setData() メソッド等を使用します。
 
書き込みアクセスは、ondragstart イベント内でのみ可能です。
 
最終的に転送データが無かった場合、ドラッグは発生しません。(一部のブラウザのみ)
 

実装例

 
ドラッグ開始時にテキストデータを指定する
 
ドラッグ開始時にテキストデータを指定する

<html>
  <body>

    <img id="aaa" style="width:200px; height:200px;" src="data:image/gif;base64,R0lGODlhAQABAJEAAP8AAAAAAP4BAgAAACH5BAQUAP8ALAAAAAABAAEAAAICRAEAOw==" >

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "aaa" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("aaa");

	// ------------------------------------------------------------
	// ドラッグ開始時に実行される関数
	// ------------------------------------------------------------
	function DragStartFunc(e){

		// DataTransfer オブジェクトを取得する
		var data_transfer = e.dataTransfer;

		// テキストデータを書き込む
		data_transfer.setData("text" , "テスト用文字列です");

	}
	
	// ------------------------------------------------------------
	// リッスンを開始する
	// ------------------------------------------------------------
	// イベントリスナーに対応している
	if(element.addEventListener){

		element.addEventListener("dragstart" , DragStartFunc);

	// アタッチイベントに対応している
	}else if(element.attachEvent){

		element.attachEvent("ondragstart" , DragStartFunc);

	}
    //-->
    </script>

  </body>
</html>
 
ドラッグ開始時にテキストデータを指定する(HTML5 世代)
 
ドラッグ開始時にテキストデータを指定する(HTML5 世代)

<html>
  <body>

    <div id="aaa" draggable="true" style="width:400px; height:300px; background:#fcc;" ></div>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "aaa" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("aaa");

	// ------------------------------------------------------------
	// ドラッグ開始時に実行されるイベント
	// ------------------------------------------------------------
	element.addEventListener("dragstart" , function (e){

		// DataTransfer オブジェクトを取得する
		var data_transfer = e.dataTransfer;

		// テキストデータを書き込む
		data_transfer.setData("text" , "テスト用文字列です");

	});

    //-->
    </script>

  </body>
</html>
 

ドラッグ操作が完了したか調べる

 
1.ドラッグ操作を追跡し続ける
 
ondrag イベントを使用します。
 
2.ドラッグ操作が完了したか監視する
 
ondragend イベントを使用します。
 
失敗した場合、dropEffect プロパティは "none" 値に変化します。
 

ドラッグ側のイベント一覧

 
■ドラッグ関連のイベント一覧
 
イベント名 解説
ondragstart DragEvent ドラッグ開始時に実行されるイベント
ondrag DragEvent ドラッグ操作中に実行されるイベント
ondragend DragEvent ドラッグ終了時に実行されるイベント(成功失敗に関係なく)
 
■使用例
 
ドラッグ関連のイベント

<html>
  <body>

    <a id="aaa" href="http://example.com" >このリンクをドラッグ!!</a>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "aaa" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("aaa");

	// ------------------------------------------------------------
	// ドラッグ開始時に実行される関数
	// ------------------------------------------------------------
	function DragStartFunc(e){
		console.log("dragstart");
	}

	// ------------------------------------------------------------
	// ドラッグ操作中に実行される関数
	// ------------------------------------------------------------
	function DragFunc(e){
		console.log("drag (dragging)");
	}

	// ------------------------------------------------------------
	// ドラッグ終了時に実行される関数
	// ------------------------------------------------------------
	function DragEndFunc(e){

		// DataTransfer オブジェクトを取得
		var data_transfer = e.dataTransfer;

		// ドラッグに成功したか
		var result = (data_transfer.dropEffect != "none");

		console.log("dragend:" + result);
	}

	// ------------------------------------------------------------
	// リッスンを開始する
	// ------------------------------------------------------------
	// イベントリスナーに対応している
	if(element.addEventListener){

		element.addEventListener("dragstart" , DragStartFunc);
		element.addEventListener("drag" , DragFunc);
		element.addEventListener("dragend" , DragEndFunc);

	// アタッチイベントに対応している
	}else if(element.attachEvent){

		element.attachEvent("ondragstart" , DragStartFunc);
		element.attachEvent("ondrag" , DragFunc);
		element.attachEvent("ondragend" , DragEndFunc);

	}
    //-->
    </script>

  </body>
</html>
 

エレメントのドラッグ操作を有効にする

 
■エレメントのドラッグ操作を有効にする
 
draggable プロパティを使用します。
 
true をセットします。
 
これにより、ondragstart イベントが、確実に発行されるようになります。
 
使用例
 
静的に draggable 属性を追加する

<html>
  <body>

    <div draggable="true" style="width:400px; height:300px; background:#fcc;" ></div>

  </body>
</html>
 
動的に draggable プロパティを追加する

// エレメントを作成する
var element = document.createElement("div");

// スタイルを設定
element.style.cssText = "width:400px; height:300px; background:#fcc;";

// エレメントのドラッグ操作を有効
element.draggable = true;

// BODY のノードリストに登録する
document.body.appendChild(element);
 
■ draggable 属性に対応していない場合
 
Internet Explorer 9 以前では、対応していません。
 
この場合、<IMG><A> 要素などで、カバーするといいでしょう。
 
これらの要素を利用すると、ondragstart イベントが、確実に発行されます。
 

ドラッグ側の許可エフェクトを設定する

 
こちらで解説しています。
 

ドラッグ操作中にイメージを表示する(HTML5世代)

 
■デフォルトの動作について
 
ドラッグした要素が、マウスカーソルに追従するように、半透明で描画されます。
 
 
■ドラッグ操作中に描画されるイメージを変更する
 
こちらで解説しています。
 
 

 

ドロップでデータを受け取る

 
 
 


ドロップでデータを受け取る

 
1.ドラッグ操作中であるか監視する(マウスカーソルが要素内に滞在中)
 
ondragover イベントを使用します。
 
登録したコールバック関数の引数から、DragEvent オブジェクトが得られます。
 
2.データの種類を事前に確認する(HTML5 世代)
 
types プロパティを使用します。
 
この段階で、データを読み取る事はできません。
 
3.ドロップを許可し受け入れを表明する
 
ondragover イベントのデフォルトの動作をキャンセルします。
 
大抵の要素は、「ドロップを受け流し、次の要素に任せる」のがデフォルトの動作です。
 
これを無効化する事で、「ドロップを受け入れる」という動作に統一されます。
 
これにより、ondrop イベントが、確実に発行されるようになります。
 
4.ドロップ操作を監視する
 
ondrop イベントを使用します。
 
登録したコールバック関数の引数から、DragEvent オブジェクトが得られます。
 
5.ドロップデータを受け取る
 
getData() メソッド等を使用します。
 
読み取りアクセスは、ondrop イベント内でのみ可能です。
 
6.デフォルトのドロップ機能を無効化する
 
こちらで解説しています。
 
URI 文字列を受け取った場合、画面の遷移が発生するので阻止します。
 

実装例

 
■テキストデータを取得する
 
テキストデータを受け取る

<html>
  <body>

    <div id="bbb" style="width:400px; height:300px; background:#ccf;" ></div>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "bbb" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("bbb");

	// ------------------------------------------------------------
	// ドラッグ操作中に実行される関数(マウスカーソルが要素内に滞在中)
	// ------------------------------------------------------------
	function DragOverFunc(e){

		// ------------------------------------------------------------
		// ドロップを許可し受け入れを表明
		// ------------------------------------------------------------
		if(e.preventDefault){
			e.preventDefault();
		}else{
			return false;
		}
	}

	// ------------------------------------------------------------
	// ドロップ時に実行される関数(データを受け取る直前)
	// ------------------------------------------------------------
	function DropFunc(e){

		// ------------------------------------------------------------
		// DataTransfer オブジェクトを取得する
		// ------------------------------------------------------------
		var data_transfer = e.dataTransfer;

		// ------------------------------------------------------------
		// テキストデータを取得する
		// ------------------------------------------------------------
		var str = data_transfer.getData("text");

		// 出力テスト
		console.log(str);

		// ------------------------------------------------------------
		// デフォルトのドロップ機能をキャンセルする
		// ------------------------------------------------------------
		if(e.preventDefault){
			e.preventDefault();
		}else{
			return false;
		}
	}

	// ------------------------------------------------------------
	// リッスンを開始する
	// ------------------------------------------------------------
	// イベントリスナーに対応している
	if(element.addEventListener){

		element.addEventListener("dragover" , DragOverFunc);
		element.addEventListener("drop" , DropFunc);

	// アタッチイベントに対応している
	}else if(element.attachEvent){

		element.attachEvent("ondragover" , DragOverFunc);
		element.attachEvent("ondrop" , DropFunc);

	}
    //-->
    </script>

  </body>
</html>
 
■「コンテンツタイプ」と「データ」を順番に取得する(HTML5 世代)
 
「コンテンツタイプ」と「データ」を順番に取得する(HTML5 世代)

<html>
  <body>

    <div id="bbb" style="width:400px; height:300px; background:#ccf;" ></div>

    <script type="text/javascript">
    <!--
	// ------------------------------------------------------------
	// "bbb" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("bbb");

	// ------------------------------------------------------------
	// ドラッグ操作中に実行されるイベント(マウスカーソルが要素内に滞在中)
	// ------------------------------------------------------------
	element.addEventListener("dragover" , function (e){
		// ドロップを許可し受け入れを表明
		e.preventDefault();
	});

	// ------------------------------------------------------------
	// ドロップ時に実行されるイベント
	// ------------------------------------------------------------
	element.addEventListener("drop" , function (e){

		// ------------------------------------------------------------
		// DataTransfer オブジェクトを取得する
		// ------------------------------------------------------------
		var data_transfer = e.dataTransfer;

		// ------------------------------------------------------------
		// コンテンツタイプのリストを取得する
		// ------------------------------------------------------------
		var type_list = data_transfer.types;
		if(!type_list) return;

		// ------------------------------------------------------------
		// データを順番に取得する
		// ------------------------------------------------------------
		var i;
		var num = type_list.length;
		for(i=0;i < num;i++){

			try{
				// コンテンツタイプを取得する
				var type = type_list[i];

				// データを取得する
				var data = data_transfer.getData(type);

				// 出力テスト
				console.log(type);
				console.log(data);

			}catch(e){
			}

		}

		// ------------------------------------------------------------
		// デフォルトのドロップ機能を無効化
		// ------------------------------------------------------------
		e.preventDefault();
	});

    //-->
    </script>

  </body>
</html>
 
■ファイルを順番に取得する(HTML5 世代)
 
ファイルを順番に取得する(HTML5 世代)

<html>
  <body>

    <div id="bbb" style="width:400px; height:300px; background:#ccf;" ></div>

    <script type="text/javascript">
    <!--
	// ------------------------------------------------------------
	// "bbb" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("bbb");

	// ------------------------------------------------------------
	// ドラッグ操作中に実行されるイベント(マウスカーソルが要素内に滞在中)
	// ------------------------------------------------------------
	element.addEventListener("dragover" , function (e){
		// ドロップを許可し受け入れを表明
		e.preventDefault();
	});

	// ------------------------------------------------------------
	// ドロップ時に実行されるイベント
	// ------------------------------------------------------------
	element.addEventListener("drop" , function (e){

		// ------------------------------------------------------------
		// DataTransfer オブジェクトを取得する
		// ------------------------------------------------------------
		var data_transfer = e.dataTransfer;

		// ------------------------------------------------------------
		// ファイルリストを取得する
		// ------------------------------------------------------------
		var file_list = data_transfer.files;
		if(!file_list) return;

		// ------------------------------------------------------------
		// ファイルを順番に取得する
		// ------------------------------------------------------------
		var i;
		var num = file_list.length;
		for(i=0;i < num;i++){

			// ファイルを取得する
			var file = file_list[i];

			// 出力テスト
			console.log("name:" + file.name);
			console.log("size:" + file.size);
			console.log("type:" + file.type);

		}

		// ------------------------------------------------------------
		// デフォルトのドロップ機能を無効化
		// ------------------------------------------------------------
		e.preventDefault();
	});

    //-->
    </script>

  </body>
</html>
 

ドロップ側のイベント一覧

 
■ドロップ関連のイベント一覧
 
イベント名 解説
ondragenter DragEvent ドラッグ操作中(マウスカーソルが要素内に侵入した時)
ondragover DragEvent ドラッグ操作中(マウスカーソルが要素内に滞在中)
ondragleave DragEvent ドラッグ操作中(マウスカーソルが要素外に撤退した時)
ondrop DragEvent ドロップ時に実行されるイベント(データを受け取る直前)
 
■使用例
 
ドロップ側のイベント

<html>
  <body>

    <div id="bbb" style="width:400px; height:300px; background:#ccf;" ></div>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "bbb" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("bbb");

	// ------------------------------------------------------------
	// ドラッグ操作中に実行される関数(マウスカーソルが要素内に侵入した時)
	// ------------------------------------------------------------
	function DragEnterFunc(e){
		console.log("dragenter");
	}

	// ------------------------------------------------------------
	// ドラッグ操作中に実行される関数(マウスカーソルが要素外に撤退した時)
	// ------------------------------------------------------------
	function DragLeaveFunc(e){
		console.log("dragleave");
	}

	// ------------------------------------------------------------
	// ドラッグ操作中に実行される関数(マウスカーソルが要素内に滞在中)
	// ------------------------------------------------------------
	function DragOverFunc(e){
		console.log("dragover");

		// ------------------------------------------------------------
		// ドロップを許可し受け入れを表明
		// ------------------------------------------------------------
		if(e.preventDefault){
			e.preventDefault();
		}else{
			return false;
		}
	}

	// ------------------------------------------------------------
	// ドロップ時に実行される関数(データを受け取る直前)
	// ------------------------------------------------------------
	function DropFunc(e){
		console.log("drop");

		// ------------------------------------------------------------
		// デフォルトのドロップ機能を無効化
		// ------------------------------------------------------------
		if(e.preventDefault){
			e.preventDefault();
		}else{
			return false;
		}
	}

	// ------------------------------------------------------------
	// リッスンを開始する
	// ------------------------------------------------------------
	// イベントリスナーに対応している
	if(element.addEventListener){

		element.addEventListener("dragenter" , DragEnterFunc);
		element.addEventListener("dragleave" , DragLeaveFunc);
		element.addEventListener("dragover" , DragOverFunc);
		element.addEventListener("drop" , DropFunc);

	// アタッチイベントに対応している
	}else if(element.attachEvent){

		element.attachEvent("ondragenter" , DragEnterFunc);
		element.attachEvent("ondragleave" , DragLeaveFunc);
		element.attachEvent("ondragover" , DragOverFunc);
		element.attachEvent("ondrop" , DropFunc);

	}
    //-->
    </script>

  </body>
</html>
 

ドロップ側のデザインについて

 
■開始のトリガーとなるイベント
 
ondragenter イベントで監視します。
 
■終了のトリガーとなるイベント
 
ondragleave と ondrop イベントで監視します。
 

ドロップ側のエフェクトを設定する

 
こちらで解説しています。
 
 

 

DragEvent について

 
 


■ DragEvent インターフェースについて

 
ドラッグやドロップ操作に関するイベント情報が格納されます。
 
■ DragEvent インターフェースの派生について
 
Event
↓派生
MouseEvent
↓派生
DragEvent
 

■ DragEvent インターフェースのプロパティについて

 
以下の読み取り専用のプロパティがあります。
 
プロパティ名説明
dataTransferDataTransferDataTransfer オブジェクトが得られる。
 

■ DataTransfer オブジェクトを取得する

 
dataTransfer プロパティを使用します。
 
■取得例
 
DragEvent から、DataTransfer オブジェクトを取得する

<html>
  <body>

    <div id="aaa" draggable="true" style="width:400px; height:300px; background:#fcc;" ></div>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// "aaa" という ID 属性のエレメントを取得する
	// ------------------------------------------------------------
	var element = document.getElementById("aaa");

	// ------------------------------------------------------------
	// ドラッグ開始時に実行されるイベント
	// ------------------------------------------------------------
	element.ondragstart = function (e){
		if(!e) e = window.event; // レガシー

		// DataTransfer オブジェクトを取得する
		var data_transfer = e.dataTransfer;

		// 出力テスト
		console.log(data_transfer);
	};

    //-->
    </script>

  </body>
</html>
 

 
 

要素のドラッグ移動について

 


ドラッグ操作による要素の移動について

 
実装に必要な API について確認します。
 

マウス関連の API について

 
マウスボタンが押されたか監視する
 
onmousedown イベントを使用します。
 
リスナーを、ドラッグしたい要素に登録します。
 
マウスの当たり判定を、任意の要素とその子孫に限定できます。
 
マウスボタンが離されたか監視する
 
onmouseup イベントを使用します。
 
リスナーを、document などの最上位に登録します。
 
マウス操作の取りこぼしを、最小限に抑える事ができます。
 
マウスカーソルの座標を取得する
 
こちらで解説しています。
 

エレメント関連の API について

 
要素の移動について
 
こちらで解説しています。
 
要素の奥行きについて
 
こちらで解説しています。
 

タスク関連の API について

 
一定の時間間隔で、任意の関数を実行する
 
こちらで解説しています。
 

実装例

 
ドラッグ操作による要素の移動

<html>
  <body>

    <div id="aaa" style="position:absolute; left:0px;   top:0px;   width:200px; height:200px; background:#fcc; cursor:move;" ></div>
    <div id="bbb" style="position:absolute; left:50px;  top:50px;  width:200px; height:200px; background:#cfc; cursor:move;" ></div>
    <div id="ccc" style="position:absolute; left:100px; top:100px; width:200px; height:200px; background:#ccf; cursor:move;" ></div>

    <script type="text/javascript">
    <!--

	// ------------------------------------------------------------
	// 各要素を取得する
	// ------------------------------------------------------------
	var element_a = document.getElementById("aaa");
	var element_b = document.getElementById("bbb");
	var element_c = document.getElementById("ccc");

	// ------------------------------------------------------------
	// 要素をドラッグ移動化
	// ------------------------------------------------------------
	var dragger_a = new ElementDragger(element_a);
	var dragger_b = new ElementDragger(element_b);
	var dragger_c = new ElementDragger(element_c);

	// ------------------------------------------------------------
	// 要素をドラッグ移動化するコンストラクタ
	// ------------------------------------------------------------
	function ElementDragger(element){
		var _this = this;

		// ------------------------------------------------------------
		// イベントハンドラ関連
		// ------------------------------------------------------------
		function mouseDown(e){
			mouse_move.x = mouse_down.x = e.clientX;
			mouse_move.y = mouse_down.y = e.clientY;
			mouse_pressed = true;

			// タスク開始
			createTask();
		};
		function mouseMove(e){
			mouse_move.x = e.clientX;
			mouse_move.y = e.clientY;
		};
		function mouseUp(e){
			mouse_move.x = e.clientX;
			mouse_move.y = e.clientY;
			mouse_pressed = false;
		};
		function dragStart(e){
			if(e.preventDefault){
				e.preventDefault();
			}else{
				return false;
			}
		};

		// ------------------------------------------------------------
		// タスク開始
		// ------------------------------------------------------------
		function createTask(){
			// 二重起動を阻止
			deleteTask();

			// ------------------------------------------------------------
			// 初期化
			// ------------------------------------------------------------
			dragging = false;
			mouse_old.x = mouse_move.x;
			mouse_old.y = mouse_move.y;

			// 現在の適用スタイルをすべて取得
			var computed_style = (function(){
				return (function(){
					var d = element.ownerDocument;
					if(!d) return null;
					var w = d.defaultView;
					if(!w) return null;
					if(!w.getComputedStyle) return null;
					return w.getComputedStyle(element);
				})() || element.currentStyle || null;
			})();

			// 要素の現在の位置を取得
			element_pos.x = parseFloat(computed_style.left) || 0;
			element_pos.y = parseFloat(computed_style.top)  || 0;

			// ------------------------------------------------------------
			// 実行
			// ------------------------------------------------------------
			time_handle = setInterval(function(){
				// マウスボタンを離した
				if(!mouse_pressed){
					// タスクを終了
					deleteTask();
					return;
				}

				// ドラッグ開始以前
				if(!dragging){

					// 少し移動してからドラッグ操作とみなす
					var x = mouse_move.x - mouse_down.x;
					var y = mouse_move.y - mouse_down.y;
					var distance = Math.sqrt(x * x + y * y);
					if(distance >= 3){

						// ドラッグ開始
						dragging = true;

						// ノードリストの最後尾に再配置(最前面化)
						var parent = element.parentNode;
						if(parent){
							parent.appendChild(element);
						}
					}
				}

				// ドラッグ操作中
				if(dragging){

					// 前回と今回の差分
					var sub_x = mouse_move.x - mouse_old.x;
					var sub_y = mouse_move.y - mouse_old.y;
					mouse_old.x = mouse_move.x;
					mouse_old.y = mouse_move.y;

					// 座標に加算
					element_pos.x += sub_x;
					element_pos.y += sub_y;

					// 要素を移動
					var style = element.style;
					style.left = (element_pos.x) + "px";
					style.top  = (element_pos.y) + "px";
				}

			},1000/60);
		};

		// ------------------------------------------------------------
		// タスク破棄
		// ------------------------------------------------------------
		function deleteTask(){
			if(time_handle === null) return;
			clearInterval(time_handle);
			time_handle = null;
		};

		// ------------------------------------------------------------
		// 開放
		// ------------------------------------------------------------
		_this.release = function(){
			// タスクを終了
			deleteTask();

			// リッスンを終了
			if(window.removeEventListener){
				element.removeEventListener("mousedown" , mouseDown);
				window.removeEventListener("mousemove" , mouseMove);
				window.removeEventListener("mouseup" , mouseUp);
				element.removeEventListener("dragstart" , dragStart);
			}else if(document.detachEvent){
				element.detachEvent("onmousedown" , mouseDown);
				document.detachEvent("onmousemove" , mouseMove);
				document.detachEvent("onmouseup" , mouseUp);
				element.detachEvent("ondragstart" , dragStart);
			}
		};

		// ------------------------------------------------------------
		// 初期化
		// ------------------------------------------------------------
		var mouse_pressed = false;
		var mouse_down = new Object();
		var mouse_move = new Object();
		var mouse_old = new Object();
		var element_pos = new Object();
		var time_handle = null;
		var dragging = false;

		// リッスンを開始
		if(window.addEventListener){
			element.addEventListener("mousedown" , mouseDown);
			window.addEventListener("mousemove" , mouseMove);
			window.addEventListener("mouseup" , mouseUp);
			element.addEventListener("dragstart" , dragStart);
		}else if(document.attachEvent){
			element.attachEvent("onmousedown" , mouseDown);
			document.attachEvent("onmousemove" , mouseMove);
			document.attachEvent("onmouseup" , mouseUp);
			element.attachEvent("ondragstart" , dragStart);
		}

	}

    //-->
    </script>

  </body>
</html>