名詞解釋
- Drag Source: 被點擊要拖曳的物件
- Drop Target: 拖曳物件要被放置的區域
 兩者分別有對應的事件可以使用,請見下圖: - 有關 Drag Source 事件
- dragstart: 當滑鼠點擊 Drag Source 時,並且拖曳的時間瞬間觸發。
- drag: 在 Drag Source 被拖曳持續觸發。
- dragend: 當滑鼠鬆開 Drag Source 時觸發。- 有關 Drop Target 事件
- dragenter: 當拖曳的 Drag Source 首次進入 Drop Target 範圍內時觸發。
- dragover: 當拖曳的 Drag Source 進入 Drop Target 範圍內時,持續觸發。
- dragleave: 當拖曳的 Drag Source 離開可放置區塊時觸發。
- drop: 當拖曳 Drag Source 在 Drop Target 的範圍內被釋放時所觸發
相關元素的前置作業
HTML Attribute
針對要拖曳的元素,在其 HTML 標籤添加屬性 draggable="true"
| 1 | <div id="drag_source" draggable="true"></div> | 
SCSS 設定
為了避免使用者在拖曳元素時選取到元素內的內容,可以在 CSS 添加以下程式碼
| 1 | [draggable="true"] { | 
基本範例說明
直接按照以下程式碼就能做出單一元素拖曳效果囉!!(僅限一次拖曳)
HTML
| 1 | <div id="drag_drop_basic"> | 
JavaScript
- Drag Source:
 將要被拖曳的元素設置- dragstart事件。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- let dragSource = document.querySelector('#drag_drop_basic #drag_source_basic'); 
 dragSource.addEventListener('dragstart', dragStart);
 dragSource.addEventListener('dragend', dragEnd);
 function dragStart(e) {
 e.dataTransfer.setData('text/plain', e.target.id);
 this.classList.add('dragging'); // 加入 dragging 自定義樣式
 }
 function dragEnd(e) {
 this.classList.remove('dragging'); // 移除 dragging 自定義樣式
 }
- Drop Target:
 對要放置的容器設置- dragenter、- dragover、- drop三個事件。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24- let dropTarget = document.querySelector('#drag_drop_basic .target_container'); 
 dropTarget.addEventListener('drop', droped);
 dropTarget.addEventListener('dragenter', cancelDefault);
 dropTarget.addEventListener('dragover', dragover);
 dropTarget.addEventListener('dragleave', dragLeave);
 function droped(e) {
 cancelDefault(e);
 let id = e.dataTransfer.getData('text/plain');
 e.target.appendChild(document.querySelector(`#${id}`));
 this.classList.remove('hover'); // 移除 hover 自定義樣式
 }
 function dragover(e) {
 cancelDefault(e);
 this.classList.add('hover'); // 加入 hover 自定義樣式
 }
 function dragLeave(e) {
 this.classList.remove('hover'); // 移除 hover 自定義樣式
 }
 // 元素預設行為是不能被放置拖曳物的,因此在拖曳對象出現在放置目標上時,取消預設行為,讓放置目標可以被放置
 function cancelDefault(e) {
 e.preventDefault();
 e.stopPropagation();
 return false; // 可加可不加
 }- 進階範例說明以下是針對多個元素進行多次拖曳的範例- HTML- 1 
 2
 3
 4
 5
 6- <div id="drag_drop_multiple"> 
 <div class="soruce_container" data-role="drag_drop_container">
 <div id="drag_source_multiple" draggable="true"></div>
 </div>
 <div class="target_container" data-role="drag_drop_container"></div>
 </div>- JavaScript
- Drag Source:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- let dragSources_multiple = document.querySelectorAll('#drag_drop_multiple #drag_source_multiple'); 
 dragSources_multiple.forEach(item => {
 item.addEventListener('dragstart', dragStart);
 item.addEventListener('dragend', dragEnd);
 });
 function dragStart(e) {
 e.dataTransfer.setData('text/plain', e.target.id);
 this.classList.add('dragging'); // 加入 dragging 自定義樣式
 }
 function dragEnd(e) {
 this.classList.remove('dragging'); // 移除 dragging 自定義樣式
 }
- Drop Target:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26- let dropTargets_multiple = document.querySelectorAll('[data-role="drag_drop_container"]'); 
 dropTargets_multiple.forEach(item => {
 item.addEventListener('drop', droped);
 item.addEventListener('dragenter', cancelDefault);
 item.addEventListener('dragover', dragover);
 item.addEventListener('dragleave', dragLeave);
 });
 function droped(e) {
 cancelDefault(e);
 let id = e.dataTransfer.getData('text/plain');
 e.target.appendChild(document.querySelector(`#${id}`));
 this.classList.remove('hover'); // 移除 hover 自定義樣式
 }
 function dragover(e) {
 cancelDefault(e);
 this.classList.add('hover'); // 加入 hover 自定義樣式
 }
 function dragLeave(e) {
 this.classList.remove('hover'); // 移除 hover 自定義樣式
 }
 // 元素預設行為是不能被放置拖曳物的,因此在拖曳對象出現在放置目標上時,取消預設行為,讓放置目標可以被放置
 function cancelDefault(e) {
 e.preventDefault();
 e.stopPropagation();
 return false; // 可加可不加
 }- 完整 DEMODEMO- 參考資料:HTML 拖放 API
 HTML 5 拖放
 使用拖曳效果,進化寶可夢吧!
 製作可拖曳的元素