html-拖拽釋放(Drag and drop) API

丶Serendipity丶發表於2022-02-23

前言

  本文總結一下html5 新增的元素拖拽功能的使用。

正文

  1、H5之前的拖拽功能實現方法

  JS 拖 拖 拽 功 能 的 實 現首先是三個事件,分別是 mousedown,mousemove,mouseup 當滑鼠點選按下的時候,需要一個 tag 標識此時已經按下,可以執行mousemove 裡面的具體方法。clientX,clientY 標識的是滑鼠的座標,分別標識橫座標和縱座標,並且我們用 offsetX 和 offsetY 來表示元素的元素的初始座標,移動的舉例應該是:滑鼠移動時候的座標-滑鼠按下去時候的座標。也就是說定位資訊為:滑鼠移動時候的座標-滑鼠按下去時候的座標+元素初始情況下的 offetLeft.還有一點也是原理性的東西,也就是拖拽的同時是絕對定位,我們改變的是絕對定位條件下的 left 以及 top等等值。

  2、H5的拖拽方法介紹

        H5中拖拽屬性:draggable: auto | true | false
        拖動事件:
        - dragstart 在元素開始被拖動時觸發
        - dragend 在拖動操作完成時觸發
        - drag 在元素被拖動時觸發
        釋放事件:
        - dragenter 被拖動元素進入到釋放區所佔據得螢幕空間時觸發
        - dragover 當被拖動元素在釋放區內移動時觸發
        - dragleave 當被拖動元素沒有放下就離開釋放區時觸發
        - drop 當被拖動元素在釋放區裡放下時觸發

        (1)將元素設定為可以拖動

        draggable="true"

        (2)拖動什麼 - ondragstart 和 setData()

        ondragstart="drag(event)"設定拖放觸發的函式
        event.dataTransfer.setData("Text",event.target.id);設定拖放的資料型別和值,Text 是一個 DOMString 表示要新增到 drag object 的拖動資料的型別。值是可拖動元素的 id ("drag1")。

        (3)放到何處 - ondragover

        該時間規定拖動元素放置在何處,預設無法將資料/元素放置在其他元素中,如果需要設定允許放置,必須阻止對元素的預設處理方式ev.preventDefault();

        (4)進行放置 - ondrop

        呼叫 preventDefault() 來避免瀏覽器對資料的預設處理(drop 事件的預設行為是以連結形式開啟)
        通過 dataTransfer.getData("Text") 方法獲得被拖的資料。該方法將返回在 setData() 方法中設定為相同型別的任何資料。
        被拖資料是被拖元素的 id ("drag1")
        把被拖元素追加到放置元素(目標元素)中

  3、使用拖拽實現小功能

<style>
    .wrap {
      width: 300px;
      margin: 0 auto;
      display: flex;
      flex-direction: row;
      justify-content: space-between;
    }
    .wrap1 {
      width: 100px;
      height: 310px;
      border: 1px solid red;
    }
    .wrap1:hover {
      box-shadow: 4px 4px 5px 3px #999;
    }
    .wrap2 {
      width: 100px;
      height: 310px;
      border: 1px solid red;
    }
    .wrap2:hover {
      box-shadow: 4px 4px 5px 3px #999;
    }
    img {
      width: 100px;
      height: 100px;
      cursor: move;
    }
    img:hover {
      box-shadow: 4px 4px 5px 3px #999;
    }
  </style>
<body>
  <div class="wrap">
    <div class="wrap1" ondragover="dragOver(event)" ondrop="drop(event,this)">
      <img src="./img/feiji1.png" draggable="true" ondragstart="dragStart(event)" id="drag1" />
      <img src="./img/feiji3.png" draggable="true" ondragstart="dragStart(event)" id="drag3" />
    </div>
    <div id="wrap2" class="wrap2" ondragenter="dragEnter(event)" ondragover="dragOver(event)" ondrop="drop(event,this)">
      <img src="./img/feiji2.png" draggable="true" ondragstart="dragStart(event)" id="drag2" />
    </div>
  </div>
  <script>
    var dragOffSetY;// 滑鼠點選下的位置相對於選擇元素的y軸長度
    function dragStart(event) {
      // 設定拖放的資料型別和值
      console.log("event.offsetY", event.offsetY);
      dragOffSetY = event.offsetY
      event.dataTransfer.setData("Text", event.target.id);
    }
    function dragOver(event) {
      event.preventDefault();
    }
    function dragEnter(event) { }
    function drop(event, thisEle) {
      event.preventDefault();
      var data = event.dataTransfer.getData("Text");
      if (thisEle.children.length * 100 - 50 > event.offsetY - dragOffSetY) {
        console.log("插入");
        // 判斷覆蓋元素的前半部分
        console.log("event.offsetY - dragOffSetY", event.offsetY, dragOffSetY);
        var offY = event.offsetY - dragOffSetY// 拖拽元素的起點位置
        console.log("拖拽元素的起點位置", offY);
        var count = Math.round(offY / 100)// 當前拖拽元素覆蓋在的元素為第幾個
        console.log("當前覆蓋元素", thisEle.children[count]);
        // 前部分
        if (count * 100 + 50 > offY) {
          thisEle.insertBefore(document.getElementById(data), thisEle.children[count]);
        } else {
          thisEle.insertBefore(document.getElementById(data), thisEle.children[count + 1]);
        }
      } else {
        console.log("追加");
        event.target.appendChild(document.getElementById(data));
      }
    }
  </script>

  執行結果如下:

寫在最後

  以上就是本文的全部內容,希望給讀者帶來些許的幫助和進步,方便的話點個關注,小白的成長之路會持續更新一些工作中常見的問題和技術點。

 

 


相關文章