jQuery UI 使えば簡単にできるけど、カスタマイズしようとするとカオスになるので、自前でも実装できるようになっておきたい。
D&Dの仕様はいろいろあるけど、以下のようなものを考えてる。
これ、何気に難しいと思う。
- ドラッグ時、掴んだ要素自体は動かさず、コピーを動かすこと
- コピーの中心は、常にマウスの位置にあること
- ドロップできる要素上をマウスホバーしたら、その要素をハイライトすること
実装手順
- ドラッグ対象要素の
mousedown
イベントを検知して、その要素のコピーを作る - ドラッグ可能エリア (大抵は
body
とか) のmousemove
イベントを検知して、コピーの位置を変える - ドロップできる要素の
mouseenter mouseleave
イベントを検知して、ハイライトのオンオフを行う - ドロップ出来る要素の
mouseup
イベントを検知して、ドロップ成功時の処理をする - ドラッグ可能エリアの
mouseup
イベントを検知して、ドロップ失敗時の処理を行う
素直に考えるとこんな風な実装になると思うけど、問題点が1つある。
コピーを動かしている間は、ドロップ出来る要素のイベントを拾えない。
解決策1: display:none + document.elementFromPoint
document.elementFromPoint(x, y)
は、x, y
の位置に見えている要素を取得するメソッド。
コピーのmousemove
イベントは拾えるので、そのタイミングでマウス位置の要素を取得し、ホバーしてる要素を検出する。
しかし、単純にそのままdocument.elementFromPoint
してもコピーしか取得できない。
そこで、コピーを一時的にdisplay: none
することでコピーの裏側を取得できるようにする。
解決策2: pointer-event:none
pointer-event
を使えばHTML要素がマウス・タッチイベントにどう反応するのかを決めることができる。
none
にすると、イベントに反応しなくなる。
ブラウザが対応していれば、コピーに pointer-event: none
を指定してやるだけで問題は解決する。
しかし、まだ対応ブラウザが限られている。
特に、IEをサポートしなければならない場合使えない。
解決策3: インラインSVGを使う
HTML5では、HTML中にSVGタグを記述できるようになった。
IEでも、IE9以上のブラウザが対応している。
実は、上記のpointer-events
はSVG要素には使えるらしい。
らしい、というのはIE9が手元にないので確認できないため。
どなたか、この方法で動くかどうか確認してくだしあ><
http://jsfiddle.net/ectJu/1/
全然ダメでした!IE9どころかIE10でも動かない!