Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Drag & Drop APIのDataTransferを使ってみる

Avatar for mame_daifuku mame_daifuku
February 20, 2025
2

Drag & Drop APIのDataTransferを使ってみる

Avatar for mame_daifuku

mame_daifuku

February 20, 2025
Tweet

Transcript

  1. 1. 動機 react-dndって何してるんだろう const [{ opacity }, dragRef] = useDrag(

    () => ({ type: ItemTypes.CARD, item: { text }, collect: (monitor) => ({ opacity: monitor.isDragging() ? 0.5 : 1 }) }),[]) const [, drop] = useDrop( () => ({ accept: ItemTypes.KNIGHT, drop: () => moveKnight(x, y) }),[x, y])
  2. ケース1:ドロップできるアイテムを制限する // ドラッグ開始時に Todo の情報を dataTransfer にセットする const handleDragStart =

    (e: DragEvent<HTMLLIElement>, todo: Todo) => { e.dataTransfer.setData('application/json', JSON.stringify(todo)); e.dataTransfer.effectAllowed = 'move'; }; // ドロップ時に、対象リストと Todo の list プロパティが一致するかチェック const handleDrop = (e: DragEvent<HTMLDivElement>, targetList: 'A' | 'B') => { e.preventDefault(); const data = e.dataTransfer.getData('application/json'); if (data) { const todo: Todo = JSON.parse(data); if (todo.list === targetList) { if (targetList === 'A') { setDroppedA(prev => [...prev, todo]); } else { setDroppedB(prev => [...prev, todo]); } } else { alert(`この Todo アイテムは ${todo.list} 用です。こちらのリストにはドロップできません。`); } } };
  3. ケース2:ドラッグ中のアイテムを変更する const handleDragStart = (e: DragEvent<HTMLLIElement>, todo: Todo) => {

    e.dataTransfer.setData('application/json', JSON.stringify(todo)); e.dataTransfer.effectAllowed = 'move'; // カスタムのドラッグイメージを作成 const dragImage = document.createElement('div'); dragImage.className = 'p-2 bg-black text-white rounded text-sm w-32 text-center'; dragImage.innerText = `Dragging: ${todo.text}`; // 一時的にドキュメントに追加してドラッグイメージに設定 document.body.appendChild(dragImage); e.dataTransfer.setDragImage(dragImage, dragImage.offsetWidth / 2, dragImage.offsetHeight / 2); // ドラッグ開始直後に削除 setTimeout(() => document.body.removeChild(dragImage), 0); };
  4. まとめ react-dndって何してるんだろう  わかる気がする!!! const [{ opacity }, dragRef] = useDrag(

    () => ({ type: ItemTypes.CARD, item: { text }, collect: (monitor) => ({ opacity: monitor.isDragging() ? 0.5 : 1 }) }),[]) const [, drop] = useDrop( () => ({ accept: ItemTypes.KNIGHT, drop: () => moveKnight(x, y) }),[x, y])