備考
特に面白くはない
ドラッグアンドドロップ周りのコードを書いたので備忘録件共有
ドラッグといえば
- DnD API
- Sortable
- Vue.Draggable
ドラッグといえば
- DnD API ← 生なのでめんどい
- Sortable
- Vue.Draggable
ドラッグといえば
- DnD API
- Sortable ← わりとカバーできる
- Vue.Draggable
ドラッグといえば
- DnD API
- Sortable
- Vue.Draggable ← SortableのWrapper
めっちゃ便利
ドラッグといえば
- DnD API
↓ ドキュメント読んで!
- Sortable
- Vue.Draggable
それでも生APIについて知りたい
ドラッグといえば
- DnD API ←←← これの話
ドラッグといえば
- DnD API
- DragEvent - Web API | MDN ← まちがい
- HTML ドラッグ&ドロップ API - Web API | MDN ← なるほどわからん
- Document: drag イベント - Web API | MDN ← せいかい
サンプルコード(MDN)
<div class="dropzone">
<div id="draggable" draggable="true" ondragstart="event.dataTransfer.setData('text/plain',null)">
This div is draggable
</div>
</div>
<div class="dropzone"></div>
<div class="dropzone"></div>
<div class="dropzone"></div>
var dragged;
/* events fired on the draggable target */
document.addEventListener("drag", function(event) {
}, false);
document.addEventListener("dragstart", function(event) {
// store a ref. on the dragged elem
dragged = event.target;
// make it half transparent
event.target.style.opacity = .5;
}, false);
document.addEventListener("dragend", function(event) {
// reset the transparency
event.target.style.opacity = "";
}, false);
/* events fired on the drop targets */
document.addEventListener("dragover", function(event) {
// prevent default to allow drop
event.preventDefault();
}, false);
document.addEventListener("dragenter", function(event) {
// highlight potential drop target when the draggable element enters it
if (event.target.className == "dropzone") {
event.target.style.background = "purple";
}
}, false);
document.addEventListener("dragleave", function(event) {
// reset background of potential drop target when the draggable element leaves it
if (event.target.className == "dropzone") {
event.target.style.background = "";
}
}, false);
document.addEventListener("drop", function(event) {
// prevent default action (open as link for some elements)
event.preventDefault();
// move dragged elem to the selected drop target
if (event.target.className == "dropzone") {
event.target.style.background = "";
dragged.parentNode.removeChild( dragged );
event.target.appendChild( dragged );
}
}, false);
event | handler | desc |
---|---|---|
drag | ondrag | …ドラッグ項目 (要素や選択テキスト) がドラッグされた場合 |
dragend | ondragend | …ドラッグ操作の終了 |
dragenter | ondragenter | …ドラッグ項目が有効なドロップ対象に入った場合 |
dragexit | ondragexit (en-US) | …要素がドラッグ操作の選択対象でなくなった場合 |
dragleave | ondragleave | …ドラッグ項目が有効なドロップ対象を離れた場合 |
dragover | ondragover | …ドラッグ項目が有効なドロップ対象にドラッグされた場合、数百ミリ秒ごとに |
dragstart | ondragstart | …ユーザーが項目をドラッグ開始した場合 |
drop | ondrop | …項目が有効なドロップ対象にドロップされた場合 |
HTMLの属性に dropable=true ってつける
- つけないとドラッグ可能要素にならない
- img タグはデフォルトで true
- trueをつければdivでもなんでもドラッグ可能
これだけだと、ドラッグはできるが
ドロップができない
drop イベントを実装する
- drop先のDOMがわかるので、自分自身を削除する
- 元のDOMから自分自身を削除する
みたいなことがMDNの例に書いてある。
まぁ、MDNが情報源でなくてもいいんだけど
dragに追従する要素はどう決まる?
dragに追従する要素はどう決まる?
- 基本:draggable=true の要素
- DataTransfer.setDragImage() - Web API | MDN によって変更できる
- できるが、setDragImage はdrag開始前に画面上にレンダリングされている画像 or DOMでなければならない
- ドラッグ時にDOMを挿入したのではおそすぎる
深堀り:DataTransfer?
- (dragstart イベントが発生した要素)から半透明の画像が生成され、ドラッグ中にマウスポインターに沿って移動します。
- このメソッドは dragstart イベントハンドラー内で呼び出す必要があります。
何が問題か?
- Vue.Draggable の
@start
イベントは、@dragstart
のラッパー的なやつなのでDataTransfarへアクセスすることができない
どうしよう?
-
@dragstart
(Vue2なら@dragstart.native
) する - 空のdivを DataTransfer.setDragImage でセットする
-
dragover
イベントでxy座標を取得してposition:absoluteにした生DOMのtop, leftをいじる- css の
transform: translate(top, left)
を用いたほうが高速かも
- css の
あとは地道にチクチクしてください
おわり。