一文搞懂drag&drop瀏覽器拖放功能的實現

来源:https://www.cnblogs.com/-867259206/p/18162266
-Advertisement-
Play Games

拖放功能,即將一個元素從一個區域,通過拖拽,放置到另一個區域。常見的應用是將文件或圖片從一個區域,拖放到另一個區域。中文常常把這表述成拖拽,實際上拖拽的描述並不准確,應該叫拖放,因為drag事件和drop事件是成對使用的,即拖拽和放置。 drag在拖拽動作發生時觸發,攜帶被拖拽元素的信息,drop在 ...


       拖放功能,即將一個元素從一個區域,通過拖拽,放置到另一個區域。常見的應用是將文件或圖片從一個區域,拖放到另一個區域。中文常常把這表述成拖拽,實際上拖拽的描述並不准確,應該叫拖放,因為drag事件和drop事件是成對使用的,即拖拽和放置。

       drag在拖拽動作發生時觸發,攜帶被拖拽元素的信息,drop在放置元素時觸發,接收傳遞的拖拽元素的信息。

       由於常常表述成拖拽,所以有些人在實現拖動功能時以為會觸發drag事件,比如側邊欄拖拽。實際上drag是為拖放功能設計的(要配合drop),拖動(or拖拽)的功能應該用mousemove事件去實現,用錯事件就會覺得怎麼拖拽功能好難啊。

P.S.

drag和mousemove事件都是在移動滑鼠的過程中觸發,所以兩個事件是會衝突的,如果發現其中一個事件不生效,可以檢查下是不是因為有元素綁定了其中一個事件,導致另一個事件沒有trigger。

具體實現

       拖放,拖拽和放置,那麼自然需要一個拖拽的區域,和一個放置的區域。

       首先,要定義允許拖拽的元素。瀏覽器的預設行為是,文本、圖像和鏈接是允許拖拽的。即<p>、<img>、<a>標簽是預設允許拖拽的,其他元素要允許拖拽,則要設置draggle="true"。這個屬性不允許簡寫。<div draggable ></div>並不會生效。

  其次,要定義拖拽的數據。比如,拖拽的是文本,則設置成文本格式,並設置拖拽的數據內容。拖拽的是圖片,則設置成圖片格式,設置數據內容。定義成圖片格式,那麼拖拽的時候,滑鼠旁邊就會顯示一張設置的圖片。設置的拖拽數據可以有多個。

      先給拖拽的元素綁定dragstart事件,再設置dataTransfer。示例代碼如下:

function dragstart_handler(ev) {
  // 添加拖拽數據
  ev.dataTransfer.setData("text/plain", ev.target.innerText);
  ev.dataTransfer.setData("text/html", ev.target.outerHTML);
  ev.dataTransfer.setData(
    "text/uri-list",
    ev.target.ownerDocument.location.href,
  );
}

       拖放相關的事件對象event中,有一個dataTranster屬性,這個屬性保存著拖放過程中的數據。並有一些屬性和方法設置和操作這些數據。

       比較常用到的屬性和方法有:

dropEffect:設置放置操作的類型,可以修改放置時滑鼠的顯示。比如設置成none,滑鼠就會顯示成禁止的樣式。

effectAllowed:設置拖放過程的操作類型,同樣影響滑鼠的顯示。

setData():設置拖放的數據。一般會在dragstart事件中用到。一個事件中,setData可以設置多個數據。但同類型的數據只能添加一項,重覆添加會被最後添加的覆蓋。

getData():檢索獲取拖放的數據。一般會在drop事件中用到。

       具體可以參考MDN文檔。

       最後,就是在drop區域中放置拖拽的元素。

       一個代碼示例:

function drop_handler(ev) {
  const data = ev.dataTransfer.getData("text/plain");
  ev.target.textContent = data;
}

       這樣,拖放就結束了。拖放功能也完成了。

       在拖放過程中,有一些全局事件觸發,可以參考下表,具體請查看MDN文檔。

事件 觸發時刻
drag 當拖拽元素或選中的文本時觸發。
dragend 當拖拽操作結束時觸發 (比如鬆開滑鼠按鍵或敲“Esc”鍵). 
dragenter 當拖拽元素或選中的文本剛進入到一個可釋放目標時觸發。
dragleave 當拖拽元素或選中的文本離開一個可釋放目標時觸發。
dragover 當元素或選中的文本被拖到一個可釋放目標上時觸發(每 100 毫秒觸發一次)。
dragstart 當用戶開始拖拽一個元素或選中的文本時觸發。
drop 當元素或選中的文本在可釋放目標上被釋放時觸發。

一些問題

但是,這樣實現拖放功能會有一些體驗問題,滑鼠的樣式顯示可能不正確。

以下是一些可能的問題:

1.禁止放置的區域沒有顯示禁止圖標。

在區域上綁定dragover事件,設置dataTransfer.dropEffect='none'並禁止預設行為e.preventDefault()

2.禁止放置的區域可以放置。

通常預設可以放置的區域是一些輸入標簽,比如<input>、<textarea>。在drop事件中,禁止預設行為e.preventDefault()可以禁止放置。

3.拖拽過程和可放置區域中,滑鼠顯示禁止圖標。

在經過或者放置的區域上,在dragover和dragenter事件中禁止預設行為e.preventDefault(),設置dataTransfernone以外的值。

4.拖拽圖片時,滑鼠旁邊沒有出現圖片。

要在dragstart事件中,設置dataTransfer為圖片類型才會顯示一張圖片。如果拖拽的不是圖片,但是希望拖拽時有拖拽元素的圖片效果顯示,也可以設置dataTransfer為圖片,設置要顯示的圖片效果,然後再設置其他的數據。dataTransfer.setData()方法是可以設置多個類型的數據的。

         這樣拖放功能的實現基本就完善了。最後在開始拖拽和放置的時候,可能會給拖拽元素和放置區域設置一些高亮的css效果,整個拖放功能的體驗就會很流暢。

 


參考:

draggable屬性:draggable - HTML(超文本標記語言) | MDN (mozilla.org)

拖放API:HTML 拖放 API - Web API | MDN (mozilla.org)

DataTransfer:DataTransfer - Web API | MDN (mozilla.org)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 效果圖,簡單的入場退場動效,一般情況是不同view之間去添加動畫,某些條件下顯然並不符合需求,需要在單個ImageView下進行的 <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintL ...
  • 隱私清單: <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><pli ...
  • 一、什麼是雙向綁定 我們先從單向綁定切入單向綁定非常簡單,就是把Model綁定到View,當我們用JavaScript代碼更新Model時,View就會自動更新雙向綁定就很容易聯想到了,在單向綁定的基礎上,用戶更新了View,Model的數據也自動被更新了,這種情況就是雙向綁定舉個慄子 當用戶填寫表 ...
  • 原創研發uniapp+vue3+pinia2跨三端仿微信app聊天模板Uniapp-Wechat。 uni-vue3-wchat基於uni-app+vue3+pinia2+uni-ui+uv-ui等技術跨端仿製微信App界面聊天項目,支持編譯到H5+小程式端+App端。實現編輯框多行消息/emoj混 ...
  • 1.現象 當在vue中列印對象的時候會發現有一些屬性或者全部屬性都是顯示的...,點擊展開後才能看到真正的值是什麼. 2.原因 因為在vue中對象都是用了代理重寫了get,由於get重寫也就導致了瀏覽器不能直接獲取到具體的值,因此才會在列印的時候為...,手動點擊展開才顯示具體的值 3.想看具體的值 ...
  • 項目結構 在開發Chrome插件時,以下幾個文件的作用如下: manifest.json:這是Chrome插件的清單文件,用於配置插件的基本信息、許可權、頁面跳轉等。其中包括插件的名稱、版本號、圖標、後臺腳本、瀏覽器動作等信息。 background.js:這是Chrome插件的後臺腳本文件,用於處理 ...
  • DevTools 非常強大除了常用的查看元素,進行斷點調試或許還有些你不知道的小技巧,小功能。如可以快速的重新發送請求,快速選擇元素,在控制臺中使用npm庫等,讓你能夠更加高效的進行開發。不定時更新~ ...
  • 大家好,我是 Java陳序員。 在日常的工作生活中,我們經常會遇到應付各類強制要求轉發朋友圈的行為,或者是朋友圈集贊的行為。 今天,給大家介紹一個工具,可以幫助你生成朋友圈轉發截圖。 關註微信公眾號:【Java陳序員】,獲取開源項目分享、AI副業分享、超200本經典電腦電子書籍等。 項目介紹 We ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...