JavaScript | ドラッグ&ドロップのイベントを実装する方法

2022-02-06JavaScript イベント,JavaScript

JavaScript | ドラッグ&ドロップのイベントを実装する方法

JavaScriptのaddeventlistener()で要素のドラッグやドロップをトリガーにした発火イベントの実装サンプルとサンプルコードを紹介しています。

「ドラッグ開始時」「ドラッグ中」「ドロップ可能エリアに入った時」「ドロップ可能エリア内にある時」「ドロップ可能エリアから離れた時」「ドラッグが終了した時」「ドロップ時の処理」のそれぞれのサンプルコードになります。

ドラッグ&ドロップのイベント実装サンプル

addeventlistener()を使ったドラッグ&ドロップのイベント処理の動作サンプルとJavascriptのサンプルコードです。

動作サンプル、サンプルコードでは、動作が確認できる最低限の記述となっています。

See the Pen JavaScript | Checkbox Event by yochans (@yochans) on CodePen.

HTMLではドラッグ可能エリアとしてclass名「.box」を付与したdivタグを5つ配置しています。

その中のひとつにドラッグ可能なアイテムとしてclass名「.item」を付与した要素を置いています。

ドラッグ可能なHTML要素にするには「draggable="true"」を指定しておきます。
これはJavaScriptで指定・解除する事も可能です。

「draggable="true"」は見た目上のドラッグを可能にする、という事に注意して下さい。サンプルではイベント処理内で「draggable="true"」の判別処理を追加していませんので、ドラッグで動かないけどドロップエリアに移動させる事ができてしまいます。

<div class="container">
	<div class="box"><div id="item" draggable="true"></div></div>
	<div class="box"></div>
	<div class="box"></div>
	<div class="box"></div>
	<div class="box"></div>
</div>

今回のサンプルでは要素に対してではなくdocumentでドラッグ&ドロップを取得しています。
この場合、ドラッグしている要素を格納する変数が必要です。サンプルでは「drag_item」としています。

各動作のaddEventListener()メゾッド内で「event」という引数を取得していますが、「ドラッグ開始時(dragstart)」「ドラッグ終了時(dragend)」では「ドラッグしたHTML要素」を取得しますが、それ以外は「ドラッグ中の位置にあるHTML要素」を取得します。

「ドラッグ開始時(dragstart)」にドラッグしている要素を格納する変数に格納して、それ以降の処理で利用します。

「ドラッグ中の位置にあるHTML要素」がドラッグ可能エリアかどうか判別して処理を作成していきます。

以下サンプルコードでは必須ではない処理をコメントアウトしていますが、その処理内容を簡単に紹介しておきます。
ドラッグ開始時(dragstart)▶ドラッグしたアイテムの透過度を下げる
ドロップ可能エリアに入った時(dragenter)▶該当エリアの背景色を変更
ドラッグ可能から外れた時(dragleave)▶該当エリアの背景色を戻す
ドラッグ終了時(dragend)▶ドラッグしていたアイテムの透過度を戻す

また、「ドロップ可能エリア内にある時(dragover)」preventDefault()メゾッドが必要です。
処理内容を把握するには、preventDefault()メゾッドについて理解しておく必要があるかもしれません。
参考:Event.preventDefault() – Web API | MDN

// ドラッグしている要素を格納する変数
let drag_item;

// ドラッグが開始された時
document.addEventListener('dragstart', () => {
	// ドラッグした要素を変数に格納
	drag_item = event.target;
	// event.target.style.opacity = 0.6;
});

// ドラッグ中 
document.addEventListener('drag', () => {
	// サンプルでは未使用
});

// ドロップ可能エリアに入った時
document.addEventListener('dragenter', () => {
	// if (event.target.className == "box") {
	// 	event.target.style.background = '#a9a9a9';
	// }
});

// ドロップ可能エリア内にある時
document.addEventListener("dragover", () => {
	event.preventDefault();
}, false);

// ドロップ可能エリアから離れた時
document.addEventListener('dragleave', () => {
	// if (event.target.className == "box") {
	// 	event.target.style.background = '';
	// }
});

// ドラッグが終了した時
document.addEventListener('dragend', () => {
	// event.target.style.opacity = 1;
});

// ドロップ時の処理
document.addEventListener("drop", () => {
	if (event.target.className == "box") {
		// event.target.style.background = '';
		drag_item.parentNode.removeChild(drag_item);
		event.target.appendChild(drag_item);
	}
	// 格納している変数を初期化(複雑化しない場合は不要かと)
	drag_item = null;
});

※このサンプルコードはアロー関数で記述したものを紹介しています。