logo

タッチ操作でドラッグ&ドロップ

スマホやタブレットでタッチ操作をしている場合、 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 でドロップを再現しているけれど、同じ要領で touchmovedragover を再現したりすることが可能。

https://codepen.io/riffrain/pen/yLLWYgq の様に、よくあるドラッグ&ドロップを簡単にするパッケージと組み合わせたり、それの拡張( https://codepen.io/riffrain/pen/yLLWYgq では、本来ドロップできない外の要素でドロップを検知している)をすることができる