Closed5

ドラッグアンドドロップの仕組みを理解する

つねみ@tocomiつねみ@tocomi

最近、ドラッグアンドドロップ(DnD)の実装を補助してくれる React 向けのライブラリ dnd kit に触れる機会があった。
ライブラリによって DnD にまつわる実装が簡易に実現できたことに感心するとともに、「ライブラリを使わない場合はどういった実装になるんだろう?」という疑問が湧いたので調べてみようと思った🧐

この記事を中心に見ていく。
https://developer.mozilla.org/ja/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations

つねみ@tocomiつねみ@tocomi

draggable 属性

https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/draggable

  • HTML の属性には draggable というものが存在する
  • default では auto
  • auto の場合、テキストの選択範囲、リンク、画像のみドラッグ可能である
    • テキストの選択範囲は任意のテキストエリアにコピーしたり
    • リンクはブラウザのタブエリアにドラッグすることでリンク先を新しいタブで開いたり
    • 画像は Mac でいう Finder にドラッグすると画像をローカルに保存したり
  • 列挙型と言われる属性であり、<div draggable> という省略形は認められない。<div draggable="true"> のように指定する。
  • 上記のデフォルトでドラッグ可能な要素以外をドラッグする場合は、draggable 属性に加えて ondragstart イベントの設定が必要

列挙型?

https://developer.mozilla.org/ja/docs/Glossary/Enumerated#html_列挙型属性

HTML の論理属性が、値が存在するか、省略されるか、または無効であるかに関わらず、属性が存在する場合は常に真となるのに対して、HTML の列挙型属性では、値が省略された場合の既定値は、無効な値の場合の既定値と異なることがあります。

HTML の属性には論理属性と列挙型があって、値を省略すると期待と違う動作をすることがある。
だから draggable は値を省略せずに指定してね、ということ?

つねみ@tocomiつねみ@tocomi

デフォルトでドラッグできない要素がドラッグ可能になる条件

  1. ドラッグできるようにしたい要素の draggable 属性の値を "true" に設定する。
  2. dragstart イベントにリスナーを設定し、そのリスナーの中でドラッグデータを設定する。
つねみ@tocomiつねみ@tocomi

dragstart イベント

以下の 3 つを設定できる

  1. ドラッグデータ(必須)
  2. フィードバック画像
  3. ドラッグの効果

ドラッグデータ

ドラッグイベントにはデータを保持するための dataTransfer と呼ばれるプロパティが割り当てられている。
dataTransfer.setData() でドロップ先に渡したいデートをセットして、ドロップ先では dataTransfer.getData() でその情報を受け取ることでドラッグされたデータを使って処理を実行できる。

https://developer.mozilla.org/ja/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#ドラッグデータ

このスクラップは2025/01/14にクローズされました