この記事では、ドラッグ&ドロップの基本について説明します。
ドラッグ可能なコンテンツを作成する
ほとんどのブラウザでは、デフォルトで選択されたテキスト、画像、リンクがドラッグ可能です。 たとえば、ウェブページ上のリンクをドラッグすると、 タイトルと URL をアドレスバーやデスクトップにドロップすると、 リンクに移動します。他の種類のコンテンツをドラッグ可能にするには、 HTML5 Drag and Drop API を使用する必要があります。
オブジェクトをドラッグ可能にするには、その要素に draggable=true
を設定します。ちょうどよい
画像、ファイル、リンク、ファイルなど、あらゆるものをドラッグ可能
使用しないでください。
次の例では、並べ替えられた列を並べ替えるインターフェースを作成します。
CSS グリッドでレイアウトを適用しました。列の基本的なマークアップは次のようになります。
各列の draggable
属性を true
に設定します。
<div class="container">
<div draggable="true" class="box">A</div>
<div draggable="true" class="box">B</div>
<div draggable="true" class="box">C</div>
</div>
以下は、コンテナ要素とボックス要素の CSS です。この CSS に関連付けられた唯一の CSS
ドラッグ機能は cursor: move
です。
プロパティです。コードの残りの部分は、コンテナのレイアウトとスタイルを制御します。
ボックス要素です。
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 10px;
}
.box {
border: 3px solid #666;
background-color: #ddd;
border-radius: .5em;
padding: 10px;
cursor: move;
}
この時点でアイテムをドラッグすることはできますが、他のことは起こりません。追加 JavaScript API を使用する必要があります。
ドラッグ イベントをリッスンする
ドラッグ プロセスをモニタリングするには、次のいずれかのイベントをリッスンします。
ドラッグ フローを処理するには、なんらかのソース要素(ドラッグ データ ペイロード(ドラッグされるもの)、ターゲット( キャッチアップ)。ソース要素には、ほぼすべての種類の要素を使用できます。「 target は、ユーザーがアクセスしているデータを受け入れるドロップ ゾーンまたは一連のドロップ ゾーンです 落とし穴について学びましたすべての要素をターゲットにできるわけではありません。たとえば、ターゲットが 使用できます。
ドラッグ シーケンスの開始と終了
コンテンツで draggable="true"
属性を定義したら、
各列のドラッグ シーケンスを開始する dragstart
イベント ハンドラ。
このコードでは、ユーザーがドラッグを開始したときに列の不透明度を 40% に設定しています。 ドラッグ イベントが終了したら 100% に戻します。
function handleDragStart(e) {
this.style.opacity = '0.4';
}
function handleDragEnd(e) {
this.style.opacity = '1';
}
let items = document.querySelectorAll('.container .box');
items.forEach(function (item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragend', handleDragEnd);
});
結果は、次の Glitch のデモで確認できます。アイテムをドラッグして
調整できます。ソース要素に dragstart
イベントがあるため、
this.style.opacity
を 40% にすると、その要素が
移動対象の現在の選択範囲。アイテムをドロップすると、ソース要素が
ドロップ動作を定義していなくても 100% の不透明度に戻ります。
視覚的な手掛かりを追加する
ユーザーがインターフェースの操作方法を理解できるように、
dragenter
、dragover
、dragleave
のイベント ハンドラ。この例では、
列はドラッグ可能であるだけでなく、ドロップ ターゲットになります。ユーザーが以下を行えるようサポートする
ドラッグしたアイテムを
選択します。たとえば、CSS で、次のような over
クラスを作成するとします。
次の要素が含まれます。
.box.over {
border: 3px dotted #666;
}
次に、JavaScript でイベント ハンドラを設定し、over
クラスを
列をドラッグして移動し、ドラッグした要素が離れたら列を削除します。イン
dragend
ハンドラでは、末尾のクラスも必ず削除します。
ドラッグします。
document.addEventListener('DOMContentLoaded', (event) => {
function handleDragStart(e) {
this.style.opacity = '0.4';
}
function handleDragEnd(e) {
this.style.opacity = '1';
items.forEach(function (item) {
item.classList.remove('over');
});
}
function handleDragOver(e) {
e.preventDefault();
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
let items = document.querySelectorAll('.container .box');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
});
このコードでは、以下の点について説明します。
デフォルトのアクション
dragover
イベントのdataTransfer.dropEffect
プロパティを"none"
。dropEffect
プロパティについては、このページの後半で説明します。現在のところ、 ただし、これによりdrop
イベントが発生しなくなります。これをオーバーライドするにはe.preventDefault()
を呼び出す必要があります。もう一つのベスト プラクティスは、 同じハンドラ内でfalse
。dragenter
イベント ハンドラは、次のようにover
クラスを切り替えるために使用されます。dragover
。dragover
を使用すると、ユーザーが操作している間にイベントが繰り返し発生します。 ドラッグしたアイテムを列の上に配置すると、CSS クラスが切り替わります 繰り返します。ブラウザでは不必要なレンダリング処理が多く ユーザーエクスペリエンスに影響する可能性がありますすべての Pod の IP アドレスを 再描画が行われます。dragover
を使用する必要がある場合は、 イベント リスナーのスロットリングまたはデバウンド。
ドロップをクリアしよう
ドロップを処理するには、drop
イベントのイベント リスナーを追加します。drop
ブラウザのデフォルトのドロップ動作を防止する必要があります。
一般的に厄介なリダイレクトですこれを行うには、e.stopPropagation()
を呼び出します。
function handleDrop(e) {
e.stopPropagation(); // stops the browser from redirecting.
return false;
}
新しいハンドラを他のハンドラとともに登録してください。
let items = document.querySelectorAll('.container .box');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
この時点でコードを実行しても、アイテムは新しい場所にドロップされません。宛先
これを行うには、DataTransfer
を使用してください。
渡されます。
dataTransfer
プロパティは、ドラッグ アクションで送信されたデータを保持します。dataTransfer
dragstart
イベントで設定され、drop イベントで読み取りまたは処理されます。発信中
e.dataTransfer.setData(mimeType, dataPayload)
を使用すると、オブジェクトの MIME を設定できます。
データ ペイロードが含まれます。
この例では、ユーザーが列の順序を変更できるようにします。 そのためには、まず、ドラッグ操作が行われたときにソース要素の HTML を保存する必要があります。 開始日:
function handleDragStart(e) {
this.style.opacity = '0.4';
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
}
drop
イベントでは、ソース列の
データをドロップしたターゲット列の HTML を HTML に変換します。この
ユーザーが操作を行った同じ列にドロップバックしていないか
表示されます。
function handleDrop(e) {
e.stopPropagation();
if (dragSrcEl !== this) {
dragSrcEl.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text/html');
}
return false;
}
結果は次のデモで確認できます。そのためには、 できます。Drag and Drop API はモバイルではサポートされていません。ドラッグ& B 列の上にある A 列を離すと、位置がどのように変わるかに注目してください。
その他のドラッグ プロパティ
dataTransfer
オブジェクトは、ユーザーに視覚的なフィードバックを提供するプロパティを公開します。
各ドロップ ターゲットがアクションにどのように反応するかを
特定できます。
dataTransfer.effectAllowed
作成する「ドラッグの種類」をユーザーが操作できる要素を指定します。使用される ドラッグ&ドロップ処理モデルでdropEffect
を初期化します。dragenter
イベントとdragover
イベント。このプロパティには、 値:none
、copy
、copyLink
、copyMove
、link
、linkMove
move
、all
、uninitialized
。dataTransfer.dropEffect
dragenter
とdragover
の間にユーザーが受け取るフィードバックを制御します。 できます。ユーザーがターゲット要素の上にポインタを置くと、ブラウザの cursor は、コピーなど、実行する操作のタイプを示します。 動きません。この効果には、none
、copy
、link
、move
。e.dataTransfer.setDragImage(imgElement, x, y)
つまり、ブラウザのデフォルトの「ゴースト画像」ではなく、フィードバックを ドラッグ アイコンを設定できます。
ファイルのアップロード
この簡単な例では、ドラッグ ソースとドラッグ ターゲットの両方に列を使用しています。この ユーザーがアイテムを並べ替えるよう求める UI で発生することがあります。場合によっては インターフェースのように、ドラッグ ターゲットとソースは異なる要素タイプになる場合があります。 商品のメイン画像として 1 つの画像を 選択した画像をターゲットにドラッグします。
ドラッグ&ドロップは、ユーザーがデスクトップからアイテムを
説明します。主な違いは drop
ハンドラにあります。代わりに、
dataTransfer.getData()
でファイルにアクセスでき、そのデータは次の場所に格納されます。
dataTransfer.files
プロパティ:
function handleDrop(e) {
e.stopPropagation(); // Stops some browsers from redirecting.
e.preventDefault();
var files = e.dataTransfer.files;
for (var i = 0, f; (f = files[i]); i++) {
// Read the File objects in this FileList.
}
}
詳しくは、このモジュールの カスタムのドラッグ&ドロップ。