[JS] ドラッグ&ドロップ

タグ :

jQuery の勉強をまとめるシリーズです。
今回はドラッグ&ドロップの使用についてまとめます。

マウス操作の究極と言っても過言ではありませんが、ドラッグ&ドロップ機能はあるのと無いのでは、サイトの印象が全然違ってきます。
様々な分野で利用可能なドラッグ&ドロップ機能は、jQuery UI を用いれば簡単に設置することが可能です。
今回は設置方法をまとめます。

プラグインのダウンロード

ドラッグ&ドロップは jQuery UI プラグインとして用意されているので、サイトからダウンロードして使用します。

サイト「http://jqueryui.com/download/

まずは、バージョンを選択します。
ダウンロードするのはドラッグ&ドロップ機能だけでいいので、一旦全ての選択を解除した後で、Draggable と Droppable をクリックして選択します。
Draggable と Droppable を選択すると上の方にある Core と Widget と Mouse が自動で選択されます。
その状態で「Download」ボタンをクリックするとダウンロードされます。
(必要ならばテーマの設定もしておきます。デフォルトのデザインでよければそのまま。)

js_dragdrop_ui_download

ダウンロードされたファイルで使用するのは以下(赤字)になります。
(ダウンロードしたバージョンは「1.9.2」です。)

このファイルを動作環境へコピーして使用します。
js フォルダ内のファイルは「(格納先のパス)/js/」へ、
css フォルダ内のファイルは「(格納先のパス)/css/」へコピーします。

コピーしたファイルは以下のように HTML で呼び出して使用します。

<link href="css/jquery-ui-1.9.2.custom.min.css" rel="stylesheet" type="text/css" />
<script src="js/jquery-1.8.3.js"></script>
<script src="js/jquery-ui-1.9.2.custom.min.js"></script>

draggable()とdroppable()

ドラッグ&ドロップを利用するには、draggable()とdroppable()の2つのメソッドを使用します。
これらメソッドには複数のオプションが設定でき、様々な動作を指定することができます。そのオプションを以下にいくつかまとめます。

[ draggable() のオプション ]
オプション 説明
containment ドラッグ可能な範囲を指定できます。指定した要素内でのみドラッグが可能にするように制限を設ける事ができます。
revert true を設定するとドラッグ後に元の位置に戻るような動作をします。ドロップキャンセル時には true を、ドロップ時には false を指定できると自然な動作になると思います。
helper ドラッグ中の表示方法を指定できます。’clone’ を設定すると要素を複製して表示するような動作となります。その他にも関数を指定して様々なエフェクトを指定することが可能です。
cursor ドラッグ中のカーソルの表示を指定できます。基本的に ‘move’ を設定することが多いと思います。
grid 要素を指定した間隔で移動させることができます。[10,10] と指定すると、上下左右に 10 ピクセル間隔で移動するような動作となります。
axis 可動方向を指定することができます。’x’ を指定すると左右のみ、’y’ を指定すると上下のみに移動可能となります。
opacity ドラッグ中の要素の不透明度を指定できます。CSS と同じ使い方です。
snap ドラッグ中の要素の端に吸い付くような動作をさせることができます。セレクタを指定することで、その要素へ吸い付き動作をするようにします。
zIndex z-index の値を指定できます。値が大きい程、手前に表示されます。
start ドラッグ開始直後に実行する処理を記述できます。
stop ドラッグ終了直後に実行する処理を記述できます。
drag ドラッグ中に実行する処理を記述できます。
[ droppable() のオプション ]
オプション 説明
accept ドロップを許可する要素を指定できます。指定にはセレクタもしくはコールバック関数を用います。
tolerance ドラッグされた要素がどの位置にあればドロップ可能位置とみなすかを指定できます。’intersect’,’fit’,’pointer’,’touch’ のどれかを指定できます。
activeClass ドロップ受け入れ可能になったときに適用される CSS のクラス名を記述します。
hoverClass ドラッグされた要素が重なったときに適用される CSS のクラス名を記述します。
activate ドロップ受け入れ可能になったときに実行される処理を記述できます。
deactivate ドロップ受け入れ不可になったときに実行される処理を記述できます。
over ドラッグされた要素が重なったときに実行される処理を記述できます。
out ドラッグされた要素が離れたときに実行される処理を記述できます。
drop ドロップが完了したときに実行される処理を記述できます。

上記のオプション以外にも指定できるオプションはあります。今回はサンプルを作成するときに使えるかなと思ったオプションについてのみを記述しました。

サンプルコード

ドラッグ&ドロップを使用するために作成するコードは以下になります。

[ 構文 ]
.draggable({ オプション })
.droppable({ オプション })
[ コード ]
$(function() {
	$('.red,.green,.blue').draggable({
		containment: '.main',
		revert: true,
		helper: 'clone',
		drag: function() {
			$(this).addClass('dragout');
		},
		stop: function() {
			$(this).removeClass('dragout');
		}
	});
	var flg = true;
	$('.drop1').droppable({
		accept: '.red,.blue',
		tolerance: 'fit',
		activeClass: 'active',
		hoverClass: 'hover',
		drop: function(e, ui) {
			/*〜 省略 (HTML要素変更処理) 〜*/
			flg = false;
		},
		deactivate: function(e, ui) {
			ui.draggable.draggable({ revert: flg });
			var obj = ui.draggable.attr('class').split(" ");
			if(obj[0] != 'blue' && flg == false) {
				flg = true;
			}
		}
	});
	$('.drop2').droppable({
		accept: '.green,.blue',
		tolerance: 'touch',
		activeClass: 'active',
		hoverClass: 'hover',
		drop: function(e, ui) {
			/*〜 省略 (HTML要素変更処理) 〜*/
			flg = false;
		},
		deactivate: function(e, ui) {
			ui.draggable.draggable({ revert: flg });
			flg = true;
		}
	});
});
<h4>ドラッグ&ドロップ</h4>
<div class="main">
	<div class="draglist">
		<div class="red">
			<p>Red</p>
		</div>
		<div class="green">
			<p>Green</p>
		</div>
		<div class="blue">
			<p>Blue</p>
		</div>
	</div>
	<div class="droparea">
		<div class="drop1">
			<p>ドロップ領域1</p>
			<p>accept = Red, Blue<br />tolerance = 'fit'</p>
			<div class="box1"></div>
			<div class="box2"></div>
			<p class="val1"></p>
			<p class="val2"></p>
		</div>
		<div class="drop2">
			<p>ドロップ領域2</p>
			<p>accept = Green, Blue<br />tolerance = 'touch'</p>
			<div class="box1"></div>
			<div class="box2"></div>
			<p class="val1"></p>
			<p class="val2"></p>
		</div>
	</div>
</div>
.main {
	width: 600px; height: 410px; background: #ccc;
}
.draglist {
	float: left; margin-top: 20px;
	width: 600px; height: 100px;
}
.red, .green, .blue {
	float: left; margin-left: 20px; cursor: move;
	width: 100px; height: 100px;
}
.red {
	background: red;
}
.green {
	background: green;
}
.blue {
	background: blue;
}
.red p, .green p, .blue p {
	margin-top: 40px; text-align: center;
}
.dragout {
	opacity: 0.4;
}
.droparea {
	float: left; margin-top: 20px;
	width: 600px; height: 250px;
}
.drop1, .drop2 {
	float: left; margin-top: 0px;
	width: 260px; height: 250px; background: gray;
	border: 2px solid black;
}
.drop1 {
	margin-left: 20px;
}
.drop2 {
	margin-left: 30px;
}
.drop1 > p, .drop2 > p {
	margin-top: 5px; margin-bottom: 0px;
	text-align: center;
}
.drop1 div, .drop2 div {
	float: left; margin-top: 20px; cursor: default;
	width: 100px; height: 100px;
}
.drop1 p.val1, .drop1 p.val2,
.drop2 p.val1, .drop2 p.val2 {
	float: left; margin-left: 20px; width: 100px;
}
.active {
	border: 2px solid red;
}
.hover {
	background: #ccc;
}
コードの説明は後述します。
赤、緑、青の3つのボックスをドラッグすることが可能です。そのボックスを下の2つのドロップ領域へドロップすることが可能ですが、ボックスによってドロップできる領域とできない領域を設定してあります。赤ボックスは領域1のみ、緑ボックスは領域2のみ、青ボックスは両方の領域へドロップすることができます。
ボックスをドラッグできる領域は薄グレー内のみに設定してあります。ボックスをドラッグすると元の位置には薄いボックスのクローンが表示されます。さらに、ドロップできない領域にドロップした場合、スススーっと元の位置に戻る動作をします。

コード解説

jQuery、HTML のコードの説明をします。

[ jQuery の説明 ]
[ 2行目〜12行目 ボックスのドラッグ設定 ]
$('.red,.green,.blue').draggable({

ドラッグできるボックスには赤、緑、青の3つ用意しました。その3つとも全く同じ動作をさせたいので、まとめて指定しています。それぞれのクラス名をカンマで区切って指定することでまとめて指定できます。

containment: '.main',
revert: true,
helper: 'clone',

ドラッグ可動範囲の指定(containment)、ドラッグ後に元の位置に戻る動作の指定(revert)、ドラッグ時に要素の複製表示する指定(helper)を行います。

drag: function() {
	$(this).addClass('dragout');
},

ドラッグ開始直後に、その要素に ‘dragout’ というクラス名を追加します。このクラス名を追加すると、CSS にてその要素の透明度が「0.4」となり、薄く表示されます。つまり、ドラッグ中は元の位置にある要素がちょっと薄く表示されるようにしています。

stop: function() {
	$(this).removeClass('dragout');
}

ドラッグ終了時には、開始時に追加したクラス名 ‘dragout’ を取り除く処理をします。この処理により、元のボックス要素が薄く表示されるのはドラッグ中のみとなります。

[ 13行目〜31行目 ドロップ領域1の設定 ]
var flg = true;

ドラッグ後に元の位置に戻る動作をするか否かを可変するためのフラグ変数を宣言します。このフラグはドロップ領域内全体で使用したいので、doroppable() メソッドの外に出しました。この変数は draggable() のオプション「revert」に直接設定する値を代入します。初期値は true で元の位置に戻る設定をするようにしています。

$('.drop1').droppable({

ドロップ領域の 1 と 2 ではドロップできる要素が異なる指定をさせたいので別々に設定します。2つの領域の違いは、ドロップ可能要素の違いとドロップ可能位置の設定くらいです。よってここでは領域1の解説のみします。

accept: '.red,.blue',
tolerance: 'fit',
activeClass: 'active',
hoverClass: 'hover',

領域1へドロップ可能とする要素は、赤ボックスと青ボックスのみです。
ドロップ可能位置は ‘fit’ とし、完全に領域内に入らないとドロップできないようにしています。
ボックスのドラッグ時にそのボックスがドロップ可能であれば、’active’ というクラス名を追加します。このクラス名を追加すると、CSS にて領域の外枠線の色が赤に変更されます。
ボックスがドロップ許可位置に入った時に ‘hover’ というクラス名を追加します。このクラス名を追加すると、CSS にて領域内の背景色が薄いグレーに変更されます。

[ 19行目〜22行目 ドロップ時に実行される処理 ]
/*〜 省略 (HTML要素変更処理) 〜*/

ここにドロップ時の HTML 要素の変更処理を記述しますが、今回は省略します。この部分の処理は次回に。。。

flg = false;

13行目で宣言した変数 flg の値を false に変更します。この変数を false にすることで、ドロップ後のボックス要素が元に戻る動作をキャンセルさせます。つまり、ドロップ領域内にドロップした場合は、ボックス要素は元に戻る動作をしないようにしています。

[ 23行目〜29行目 ドロップ終了時に実行される処理 ]
deactivate: function(e, ui) {

deactivate オプションはドロップ受け入れ不可になったときに実行されるとありますが、accept オプションで指定した要素のドロップ終了時に実行されます。ドロップ領域内であろうが、領域外であろうがドロップが終了したときの全てで実行されます。

ui.draggable.draggable({ revert: flg });

ドロップ終了時に要素が元に戻る動作をさせるか否かを設定し直します。設定値には、変数 flg を使用しています。そのため、ドロップ領域内にドロップされたときは、元の位置に戻らないように設定され、領域外にドロップされたときは元の位置に戻るように設定されます。

var obj = ui.draggable.attr('class').split(" ");
if(obj[0] != 'blue' && flg == false) {
	flg = true;
}

変数 flg の初期化を行います。今回のサンプルの青ボックスのようにドロップ可能領域が複数存在する場合、deactivate オプションの処理が両方とも実行されてしまいます。そのため、2回目(.drop2)の実行で確実に true が設定されてしまいますので、それを防止するためにこのような条件分岐でフラグの初期化を回避しています。

[ HTML の説明 ]
[ 2行目〜32行目 ドラッグ可動領域 ]

ボックスをドラッグして移動できる範囲はこの div 要素内になります。

[ 3行目〜13行目 ドラッグできるボックス部 ]

ドラッグできるボックスを表示します。ボックスは赤、緑、青の3つ用意します。

[ 14行目〜31行目 ドロップ領域部 ]

ドロップできる領域を表示します。領域は2つ用意します。
領域内には空の div 要素と p 要素を用意し、ドロップした際に表示されるボックス領域を予め用意しておきます。ドロップされた時にこの領域が変更されることでドロップされたと見せるようにしています。

まとめ

指定できるオプションが多いので、難しいように思われますが、ほとんどデフォルトの設定値で十分な動作が可能です。気に入らない動作があるならオプションにて設定し直せばいいのです。
中にはオプションの設定変更だけでは変えられない動作もありますが、ある程度の設定はこのオプションで賄えます。

このドラッグ&ドロップ機能は、買い物アプリ内などで使用すると便利かもしれません。買い物カゴへ商品をドラッグして移動し、ドロップすることでカゴへ商品を入れるという動作になります。
ボタンのワンクリックで買い物カゴに入れるようにした方が簡単で早いですが、その操作がユーザーにとって簡易的な操作かどうかは気にせず、楽しんで操作できるかという部分においては非常に効果的だと思います。

サンプルで作成したものはここで説明した UI の設置と設定以外に、ドロップ後の処理が必要になります。jQuery コードの省略した部分に記述する内容がソレです。これについては次回の記事で説明したいと思います。

Share

  • このエントリーをはてなブックマークに追加

Comment

コメントを残す

*がついている欄は必須項目です。

  • Twitter
  • Facebook
  • Google Plus
  • RSS Feed