1. 程式人生 > >使用 Drag and Drop 給Web應用提升互動體驗

使用 Drag and Drop 給Web應用提升互動體驗

什麼是 Drag and Drop (拖放)?

簡單來說,HTML5 提供了 Drag and Drop API,允許使用者用滑鼠選中一個可拖動元素,移動滑鼠拖放到一個可放置到元素的過程。

我相信每個人都或多或少接觸過拖放,比如瀏覽器多標籤頁之間的可拖放排序、手機中的App可以隨便拖放排序等等,Drag and Drop 已經給我們提供了更便捷、更靈活的網路應用體驗。

HTML5 Drag and Drop

DnD 規範定義了基於事件的拖放機制和附加標記,以標記網頁上幾乎所有 draggable 的元素型別,一個典型的 drag 操作是這樣開始的:使用者用滑鼠選中一個可拖動的(draggable)元素,移動滑鼠到一個可放置的(droppable)元素,然後釋放滑鼠。 在操作期間,會觸發一些事件型別,有一些事件型別可能會被多次觸發(比如drag 和 dragover 事件型別)。

總結起來很簡單:

Drag Source(What to drag) => Drop Target(Where to drop)

dnd-example

拖拽事件

所有的拖拽事件都對應一個 global event handler,Dnd API 一個有8個事件,可以分為繫結在 Drag Source 上3個、繫結在 Drag Target 上5個

Drag Source

Event Description
dragstart 當用戶開始拖動一個元素或選中的文字時觸發。
drag 當拖動元素或選中的文字時觸發。
dragend 當拖拽操作結束時觸發 (比如鬆開滑鼠按鍵或敲“Esc”鍵)。

Drop Target

Event Description
dragenter 當拖動元素或選中的文字到一個可釋放目標時觸發。
dragover 當元素或選中的文字被拖到一個可釋放目標上時觸發(每100毫秒觸發一次)。
dragexit 當元素變得不再是拖動操作的選中目標時觸發。
dragleave 當拖動元素或選中的文字離開一個可釋放目標時觸發。
drop 當元素或選中的文字在可釋放目標上被釋放時觸發。

dnd-event-flow

注意點

  • 在滑鼠操作拖放期間,有一些事件可能觸發多次,(比如:dragdragover)。使用時注意防抖節流
  • dragover 事件中使用 event.preventDefault() 阻止預設事件行為時,才能正確觸發 drop 事件
  • 在 Firefox 瀏覽器中觸發 drop 時要使用 event.preventDefault() 阻止預設事件行為,以防止開啟一個新的標籤

資料介面

HTML拖拽的資料介面有三個 DataTransferDataTransferItemDataTransferItemList

在進行拖放操作時,DataTransfer 物件用來儲存,通過拖放動作,拖動到瀏覽器的資料。它可以儲存一項或多項資料、一種或者多種資料型別。

DataTransfer 常用屬性

屬性 型別 描述
dropEffect String 獲取 / 設定實際的放置效果,它應該始終設定成 effectAllowed 的可能值之一,copymovelinknone
effectAllowed String 用來指定拖動時被允許的效果。
Files FileList 儲存一個被儲存資料的型別列表作為第一項,順序與被新增資料的順序一致。如果沒有新增資料將返回一個空列表。
types DOMStringList 包含一個在資料傳輸上所有可用的本地檔案列表。如果拖動操作不涉及拖動檔案,此屬性是一個空列表。

DataTransfer 常用方法

  • void clearData([in String type])
  • String getData(in String type)
  • void setData(in String type, in String data)
  • void setDragImage(in nsIDOMElement image, in long x, in long y)

dnd-data

注意點

  • 通過定義 MIME (Multipurpose Internet Mail Exchange)來指定資料傳輸型別,例如:text/plain

功能檢測

想象一下我們想開發一個使用HTML5 DnD API來實現的豐富可互動式的應用。結果因為瀏覽器不支援,是不是很糟糕。對我們是否需要使用降級方案還是有很重要的參考意義的。

下面有兩種常用的方法來幫助我們來檢測。

caniuse

caniuse-dnd

Modernizr

Modernizr 是一個出色的可用於檢測使用者瀏覽器是否支援 HTML5CSS3 功能的庫。

if (Modernizr.draganddrop) {
  // Browser supports HTML5 DnD.
} else {
  // Fallback to a library solution.
}
複製程式碼

實現拖拽

HTML Attribute

實現拖拽元素只需要在dom標籤上加入 draggable="true"

<div id="drag-source" draggable="true"></div>
複製程式碼

CSS User Interface

user-select

可拖拽元素,建議使用 user-select,避免使用者在拖拽時選取到內部元素。

[draggable="true"] {
  /*
   To prevent user selecting inside the drag source
  */
  user-select: none;
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
}
複製程式碼

cursor

可拖拽元素,建議使用 cursor,設定可拖拽元素的滑鼠遊標,提升互動。

[draggable="true"] {
  cursor: move;
}
複製程式碼

在 Vue 中使用拖拽

Vue 中使用 dnd 可以直接繫結 event 到元件上。

下面栗子包含的內容:

  • 使用Vue實現拖放
  • 拖放事件以及事件觸發的時機
  • 拖放事件的一些效果處理
  • 拖拽系統檔案到瀏覽器

Edit DnD Demo

DnD 能做什麼?

  • 提升網頁上操作互動體驗
  • 提供列表排序功能
  • 本機與瀏覽器互動
  • HTML5遊戲

推薦一些不錯的DnD庫

  • interact.js - JavaScript drag and drop, resizing and multi-touch gestures with inertia and snapping for modern browsers (and also IE9+)
  • Sortable - Sortable — is a JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices.
  • draggable - The JavaScript Drag & Drop library your grandparents warned you about.
  • Vue.Draggable - Vue component allowing drag-and-drop sorting in sync with View-Model. Based on Sortable.js
  • vue-grid-layout - A draggable and resizable grid layout, for Vue.js.
  • vue-draggable-resizable - Vue2 Component for draggable and resizable elements.
  • react-dnd - Drag and Drop for React
  • react-beautiful-dnd - Beautiful and accessible drag and drop for lists with React
  • react-grid-layout - A draggable and resizable grid layout with responsive breakpoints, for React.

參考

Mozilla HTML_Drag_and_Drop_API

Native HTML5 Drag and Drop

caniuse

Working with HTML5 Drag-and-Drop

原文:使用 Drag and Drop 給Web應用提升互動體驗