スマホやタブレットでタッチ操作をしている場合、 DragEvent が使えないため、 TouchEvent を利用して擬似的にドラッグ&ドロップを実現する必要がある。
本記事はそのヒント。
まずはじめに、ドロップイベントを実現するには、 touchend
イベントと document.elementFromPoint を組み合わせればよい。
touchend
イベントが発火した場所の要素を document.elementFromPoint
で取得し、その取得できた要素がなにかを判定して、すきな処理を行えばよい。
例:
/**
* @param {Event} event イベントオブジェクト
* @return {Element|null}
*/
const getElementFromEventPoint = (event) => {
const { clientX, clientY } = /^touch/.test(event.type)
? event.changedTouches[0] // touchstart|touchmove|touchendの場合はこちらから座標を取得
: event; // その他(マウスやポインタ)のイベントの場合は、こちらから座標を取得
return document.elementFromPoint(clientX, clientY); // 座標から要素を取得
}
let isDragging = false;
window.addEventListener('touchstart', () => {
isDragging = true;
});
window.addEventListener('touchend', (event) => {
if (!isDragging) {
return;
}
isDragging = false;
const el = getElementFromEventPoint(event);
// イベントが発生した座標の要素に `data-drop-zone` 属性が付与されていたらなにかしら処理する
if (el && typeof el.dataset.dropZone !== 'undefined') {
// 処理...
}
});
この例では、 touchend
でドロップを再現しているけれど、同じ要領で touchmove
で dragover
を再現したりすることが可能。
https://codepen.io/riffrain/pen/yLLWYgq の様に、よくあるドラッグ&ドロップを簡単にするパッケージと組み合わせたり、それの拡張( https://codepen.io/riffrain/pen/yLLWYgq では、本来ドロップできない外の要素でドロップを検知している)をすることができる