原生JS快速實現拖放(drag and drop)效果

拖放是很常見的一種交互效果,不少時候咱們都會藉助於第三方的控件來實現,其實用原生js實現起來也很是的方便。接下來咱們就用原生js和css快速實現這樣的拖放效果:css

圖片描述

HTML

HTML的內容很簡單,就是五個空的容器和一個能夠被拖拽的元素:html

html:app

<body>
  <div class="droppable">
    <div class="draggable" draggable="true"></div>
  </div>
  <div class="droppable"></div>
  <div class="droppable"></div>
  <div class="droppable"></div>
  <div class="droppable"></div>
</body>
注意點: 1. 容器的的 classdroppable,用於接收被拖拽的元素,可被拖拽的元素 classdraggable,同時設置 draggable屬性爲 true,表示該元素能夠被拖拽。 2. 默認狀況下,只有圖片、連接還有被選中的文字能被拖拽,其餘元素須要設置 draggabletrue才能被拖拽。因此爲了凸顯 draggable的用法,這裏使用 <div>而不是 <image>來做爲被拖拽的元素。

CSS

在實現樣式的時候,除了實現靜態的樣式,一些過渡狀態也須要增長樣式以提高視覺體驗:1. 元素被拖動的過程當中增長邊框等效果;2. 當元素被拖動到容器上方時,容器也應增長樣式代表容器能夠接收一個被拖拽的元素。dom

css:異步

body {
  background-color: darksalmon;
}

.draggable {
  background-image: url('http://source.unsplash.com/random/150x150');
  position: relative;
  height: 150px;
  width: 150px;
  top: 5px;
  left: 5px;
  cursor: pointer;
}

.droppable {
  display: inline-block;
  height: 160px;
  width: 160px;
  margin: 10px;
  border: 3px salmon solid;
  background-color: white;
}

.dragging {
  border: 4px yellow solid;
}

.drag-over {
  background-color: #f4f4f4;
  border-style: dashed;
}

.invisible {
  display: none;
}
注意點: 1. 圖片來源於 https://source.unsplash.com/的隨機圖片; 2. .dragging爲draggable元素正在被拖動的狀態,增長黃色border; 3. .drag-over爲draggable元素被拖動到容器上方時容器的狀態,增長灰色虛線border。

JS

最後,咱們須要經過js監聽draggabledroppable的相關的事件。this

js:url

// 查詢draggable和droppable
const draggable = document.querySelector('.draggable');
const droppables = document.querySelectorAll('.droppable');

// 監聽draggable的相關事件
draggable.addEventListener('dragstart', dragStart);
draggable.addEventListener('dragend', dragEnd);

function dragStart() {
  this.className += ' dragging';
  setTimeout(() => {
    this.className = 'invisible';
  }, 0);
}

function dragEnd() {
  this.className = 'draggable';
}

// 監聽droppable的相關事件
for (const droppable of droppables) {
  droppable.addEventListener('dragover', dragOver);
  droppable.addEventListener('dragleave', dragLeave);
  droppable.addEventListener('dragenter', dragEnter);
  droppable.addEventListener('drop', dragDrop);
}

function dragOver(e) {
  e.preventDefault();
}

function dragEnter(e) {
  e.preventDefault();
  this.className += ' drag-over';
}

function dragLeave(e) {
  this.className = 'droppable';
}

function dragDrop(e) {
  this.className = 'droppable';
  this.append(draggable);
}
注意點: 1. 當draggable元素被拖動時,原來容器中的draggable元素並不會消失,須要咱們手動將其隱藏( class設置爲 invisible),若是同步操做會立馬觸發 dragend事件致使拖動效果消失,因此在 setTimeout的回調中異步設置可確保拖動操做開始後再隱藏draggable元素; 2.dragEnterdragOver方法中咱們須要經過 preventDefault來取消事件以代表容器是一個合法的 droppable元素,否則容器的 drop事件將沒法觸發,接下來的操做也將沒法進行,詳細解釋請參考 MDN DropTarget3.dragDrop方法中直接使用 append方法將 draggable元素移動至當前容器下面。

好了,demo比較簡單,可是細節仍是有一些的,本身實踐一下才能更深入的領悟。spa

完整示例:https://codepen.io/mudontire/...code

相關文章
相關標籤/搜索