VanillaJavaScriptとHTMLを使用してドラッグアンドドロップ要素を作成する方法
序章
ドラッグアンドドロップは、多くのグラフィカルユーザーインターフェイスで見られる一般的なユーザー操作です。
ドラッグアンドドロップ機能をアプリに追加するための既存のJavaScriptライブラリがあります。 ただし、ライブラリが利用できない場合や、プロジェクトに必要のないオーバーヘッドや依存関係が生じる場合があります。 このような状況では、最新のWebブラウザーで使用できるAPIの知識により、代替ソリューションを提供できます。
HTMLドラッグアンドドロップAPIは、DOMのイベントモデルに依存して、ドラッグまたはドロップされているものに関する情報を取得し、ドラッグアンドドロップでその要素を更新します。 JavaScriptイベントハンドラーを使用すると、任意の要素をドラッグ可能なアイテムまたはドロップできるアイテムに変えることができます。
このチュートリアルでは、HTMLドラッグアンドドロップAPIとバニラJavaScriptを使用して、イベントハンドラーを使用するドラッグアンドドロップの例を作成します。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- ドラッグアンドドロップAPI(Chrome 4以降、Firefox 3.5以降、Safari 3.1以降、Edge 18以降)をサポートする最新のWebブラウザー。
ステップ1—プロジェクトと初期マークアップの作成
私たちのプロジェクトは、2種類の子要素を持つコンテナで構成されます。
- ドラッグできる子要素
- 要素をドロップできる子要素
まず、ターミナルウィンドウを開き、新しいプロジェクトディレクトリを作成します。
mkdir drag-and-drop-example
次に、そのディレクトリに移動します。
cd drag-and-drop-example
次に、そのディレクトリにindex.html
ファイルを作成します。
nano index.html
次に、HTMLWebページのボイラープレートコードを追加します。
index.html
<!DOCTYPE html> <html> <head> <title>My Drag-and-Drop Example</title> <link rel="stylesheet" href="style.css" /> </head> <body> </body> </html>
そして、<body>
タグの間に、draggable
アイテムとdropzone
(ドロップターゲット)を追加します。
index.html
<div class="example-parent"> <div class="example-origin"> <div id="draggable-1" class="example-draggable" > draggable </div> </div> <div class="example-dropzone" > dropzone </div> </div>
ファイルを保存して閉じます。 次に、style.css
ファイルを作成します。
nano style.css
次に、index.html
ファイルに要素のスタイルを追加します。
style.css
.example-parent { border: 2px solid #DFA612; color: black; display: flex; font-family: sans-serif; font-weight: bold; } .example-origin { flex-basis: 100%; flex-grow: 1; padding: 10px; } .example-draggable { background-color: #4AAE9B; font-weight: normal; margin-bottom: 10px; margin-top: 10px; padding: 10px; } .example-dropzone { background-color: #6DB65B; flex-basis: 100%; flex-grow: 1; padding: 10px; }
これにより、アプリにフォーマットが追加されます。 これで、ブラウザでindex.html
を表示し、draggable
<div>
とdropzone
<div>
が生成されることを確認できます。
次に、draggable
属性を追加して、最初の<div>
を明示的にドラッグ可能にします。
index.html
<div class="example-parent"> <div class="example-origin"> <div id="draggable-1" class="example-draggable" draggable="true" > draggable </div> </div> <div class="example-dropzone" > dropzone </div> </div>
ファイルを保存して閉じます。
最後に、ブラウザでindex.html
をもう一度表示します。 draggable
<div>
をクリックして画面上でドラッグすると、移動していることが視覚的に示されます。
draggable
属性のデフォルト値はauto
です。 つまり、要素がドラッグ可能かどうかは、ブラウザのデフォルトの動作によって決まります。 通常、これは、draggable="true"
を指定せずに、テキストの選択、画像、およびリンクをドラッグできることを意味します。
これで、ドラッグ可能な要素を含むHTMLファイルができました。 onevent
ハンドラーの追加に進みます。
ステップ2—JavaScriptを使用したドラッグアンドドロップイベントの処理
現在、ドラッグ可能な要素をドラッグしているときにマウスを離しても、何も起こりません。 DOM要素のドラッグアンドドロップでアクションをトリガーするには、ドラッグアンドドロップAPIを利用する必要があります。
ondragstart
:このイベントハンドラーはdraggable
要素にアタッチされ、dragstart
イベントが発生したときに発生します。ondragover
:このイベントハンドラーはdropzone
要素にアタッチされ、dragover
イベントが発生したときに発生します。ondrop
:このイベントハンドラーはdropzone
要素にもアタッチされ、drop
イベントが発生したときに発生します。
注:合計8つのイベントハンドラーがあります:ondrag
、ondragend
、ondragenter
、ondragexit
、ondragleave
、ondragover
、ondragstart
、およびondrop
。 この例では、それらすべてを必要としません。
まず、index.html
内の新しいscript.js
ファイルを参照しましょう。
index.html
<body> ... <script src="script.js"></script> </body>
次に、新しいscript.js
ファイルを作成します。
nano script.js
DataTransfer
オブジェクトは、現在発生しているドラッグに関連する情報を追跡します。 ドラッグアンドドロップで要素を更新するには、DataTransfer
オブジェクトに直接アクセスする必要があります。 これを行うには、DOM要素のDragEvent
からdataTransfer
プロパティを選択します。
注: DataTransfer
オブジェクトは、同時にドラッグされている複数の要素の情報を技術的に追跡できます。 この例では、1つの要素のドラッグに焦点を当てます。
dataTransfer
オブジェクトのsetData
メソッドを使用して、現在ドラッグされている要素のドラッグ状態情報を設定できます。 2つのパラメータが必要です。
- 2番目のパラメーターの形式を宣言する文字列
- 転送される実際のデータ
私たちの目標は、draggable
要素を新しい親要素に移動することです。 一意のid
を持つdraggable
要素を選択できる必要があります。 ドラッグした要素のid
は、後で使用できるようにsetData
メソッドで設定できます。
script.js
ファイルに戻り、setData
を使用する新しい関数を作成しましょう。
script.js
function onDragStart(event) { event .dataTransfer .setData('text/plain', event.target.id); }
注: Internet Explorer 9〜11には、'text/plain'
の使用に問題があると報告されています。 そのブラウザのフォーマットは'text'
である必要があります。
ドラッグされたアイテムのCSSスタイルを更新するには、DOMイベントを再度使用し、currentTarget
に必要なスタイルを設定することでそのスタイルにアクセスできます。
関数に追加して、backgroundColor
をyellow
に変更しましょう。
script.js
function onDragStart(event) { event .dataTransfer .setData('text/plain', event.target.id); event .currentTarget .style .backgroundColor = 'yellow'; }
注:ドラッグのみのスタイルが必要な場合は、変更したスタイルをドロップ時に手動で再度更新する必要があります。 ドラッグの開始時に何かを変更した場合、ドラッグした要素は、元に戻さない限り、その新しいスタイルを維持します。
これで、ドラッグを開始するときのJavaScript関数ができました。
index.html
のdraggable
要素にondragstart
を追加できます。
index.html
<div class="example-parent"> <div class="example-origin"> <div id="draggable-1" class="example-draggable" draggable="true" ondragstart="onDragStart(event);" > draggable </div> </div> <div class="example-dropzone"> dropzone </div> </div>
ブラウザでindex.html
を表示します。 ここでアイテムをドラッグしようとすると、関数で宣言されたスタイルが適用されます。
ただし、クリックを離しても何も起こりません。
このシーケンスで起動される次のイベントハンドラーはondragover
です。
ブラウザの<div>
などの特定のDOM要素のデフォルトのドロップ動作は、通常、ドロップを受け入れません。 この動作は、実装しようとしている動作をインターセプトします。 目的のドロップ動作を確実に得るために、preventDefault
を適用します。
script.js
ファイルに戻り、preventDefault
を使用する新しい関数を作成してみましょう。 次のコードをファイルの最後に追加します。
script.js
function onDragOver(event) { event.preventDefault(); }
これで、index.html
のdropzone
要素にondragover
を追加できます。
index.html
<div class="example-parent"> <div class="example-origin"> <div id="draggable-1" class="example-draggable" draggable="true" ondragstart="onDragStart(event);" > draggable </div> </div> <div class="example-dropzone" ondragover="onDragOver(event);" > dropzone </div> </div>
この時点では、実際のドロップを処理するコードはまだ作成されていません。 このシーケンスで発生する最後のイベントハンドラーはondrop
です。
script.js
ファイルに戻り、新しい関数を作成しましょう。
dataTransfer
オブジェクトのsetData
メソッドを使用して、以前に保存したデータを参照できます。 dataTransfer
オブジェクトのgetData
メソッドを使用します。 私たちが設定したデータはid
だったので、それが私たちに返されます。
script.js
function onDrop(event) { const id = event .dataTransfer .getData('text'); }
取得したid
を含むdraggable
要素を選択します。
script.js
function onDrop(event) { // ... const draggableElement = document.getElementById(id); }
dropzone
要素を選択します。
script.js
function onDrop(event) { // ... const dropzone = event.target; }
draggable
要素をdropzone
に追加します。
script.js
function onDrop(event) { // ... dropzone.appendChild(draggableElement); }
dataTransfer
オブジェクトをリセットします。
script.js
function onDrop(event) { // ... event .dataTransfer .clearData(); }
これで、index.html
のdropzone
要素にondrop
を追加できます。
index.html
<div class="example-parent"> <div class="example-origin"> <div id="draggable-1" class="example-draggable" draggable="true" ondragstart="onDragStart(event);" > draggable </div> </div> <div class="example-dropzone" ondragover="onDragOver(event);" ondrop="onDrop(event);" > dropzone </div> </div>
これが完了すると、ドラッグアンドドロップ機能が完成します。 ブラウザでindex.html
を表示し、draggable
要素をdropzone
にドラッグします。
この例では、単一のドラッグ可能なアイテムと単一のドロップターゲットのシナリオを処理します。 複数のドラッグ可能なアイテム、複数のドロップターゲットを設定し、他のすべてのドラッグアンドドロップAPIイベントハンドラーを使用してカスタマイズできます。
ステップ3—複数のドラッグ可能なアイテムを使用して高度な例を作成する
このAPIの使用方法のもう1つの例は、"To-do"
列から"Done"
列に移動できるドラッグ可能なタスクを含むToDoリストです。
独自のやることリストを作成するには、一意のid
を含むドラッグ可能な要素をindex.html
に追加します。
index.html
<div class="example-parent"> <h1>To-do list</h1> <div class="example-origin"> To-do <div id="draggable-1" class="example-draggable" draggable="true" ondragstart="onDragStart(event);" > thing 1 </div> <div id="draggable-2" class="example-draggable" draggable="true" ondragstart="onDragStart(event);" > thing 2 </div> <div id="draggable-3" class="example-draggable" draggable="true" ondragstart="onDragStart(event);" > thing 3 </div> <div id="draggable-4" class="example-draggable" draggable="true" ondragstart="onDragStart(event);" > thing 4 </div> </div> <div class="example-dropzone" ondragover="onDragOver(event);" ondrop="onDrop(event);" > Done </div> </div>
ブラウザでindex.html
を表示し、To-do列の項目をDone列にドラッグします。 To Doアプリケーションを作成し、機能をテストしました。
結論
この記事では、最新のWebブラウザーで使用できるドラッグアンドドロップ機能を調べるためのToDoアプリを作成しました。
ドラッグアンドドロップAPIは、ドラッグアンドドロップ以外のアクションをカスタマイズするための複数のオプションを提供します。 たとえば、ドラッグしたアイテムのCSSスタイルを更新できます。 また、アイテムを移動する代わりに、ドラッグ可能なアイテムをコピーして、ドロップ時に複製されるようにすることもできます。
多くのWebブラウザーはこのテクノロジーをサポートしていますが、オーディエンスがこの機能をサポートしないデバイスで構成されている場合は、このテクノロジーに依存できない可能性があることに注意してください。
ドラッグアンドドロップAPIを使用してドロップできるすべての詳細については、MDNのドキュメントを確認してください。