終于弄懂了HTML5的拖放API(1)

HTML5的拖放(drag和drop)第一部分

拖放即抓取對象以后拖到另一個位置侣颂。HTML5中任何元素都能夠拖放档桃。

先來看一個簡單的示例了解拖放是什么?

可以看到用戶可使用鼠標(biāo)選擇可拖拽元素憔晒,將元素拖拽到可放置元素藻肄,并釋放鼠標(biāo)按鈕以放置這些元素。拖拽操作期間拒担,會有一個可拖拽元素的半透明快照跟隨著鼠標(biāo)指針嘹屯。

[圖片上傳失敗...(image-8d5426-1690085058496)]

核心代碼:

<div
     id="dropBox"
     ondrop="drop(event)"
     ondragover="allowDrop(event)">
</div>
<br>
<div
     id="dragBox"
     draggable="true"
     ondragstart="drag(event)">
    可以把我拖到矩形框中
</div>

<script>
    function allowDrop(ev) {
        ev.preventDefault();
    }
    function drag(ev) {
        ev.dataTransfer.setData("Text", ev.target.id);
    }
    function drop(ev) {
        ev.preventDefault();
        const data = ev.dataTransfer.getData("Text");
        ev.target.appendChild(document.getElementById(data));
    }
</script>

我們可以把拖放操作拆解為兩個部分:一個部分是針對可拖拽元素,另一個部分針對放置元素从撼。

可拖拽元素

draggable 屬性

draggable屬性是一種枚舉類型屬性(不是布爾類型)州弟,用來標(biāo)識元素是否運行使用瀏覽器原生行為或HTML拖放操作。draggable不能用于SVG元素低零,只能用于嚴(yán)格屬于HTML的元素婆翔。

draggable的取值:

  • dragable="true":元素可以被拖動
  • dragable="false":元素不可用被拖動

如果不設(shè)置draggable默認(rèn)為auto

在HTML中毁兆,除了圖像浙滤、鏈接和選中的文本有默認(rèn)的可拖拽行為以為,其他元素在默認(rèn)情況下是不可拖拽的气堕。**

要使其他的HTML元素可拖拽纺腊,必須:

  • 將要拖拽到元素的draggable屬性設(shè)為true
  • 給可拖拽元素添加dragstart事件茎芭;
  • dragstart中設(shè)置拖拽數(shù)據(jù)揖膜。

dragstart 事件

當(dāng)用戶開始拖拽操作時,會觸發(fā)dragstart事件梅桩。即在用戶開始拖動元素或被選擇的文本時調(diào)用壹粟。

dragstart事件被添加到可拖拽元素本身。我們也可以監(jiān)聽它的祖先元素宿百,因為拖拽事件會冒泡趁仙。

dragstart事件可以做什么操作?

dragstart事件中垦页,我們可以指定拖拽數(shù)據(jù)雀费、反饋圖像拖拽效果

拖拽數(shù)據(jù)

所有的拖拽事件中都有dataTransfer屬性痊焊,它上面掛有拖拽數(shù)據(jù)盏袄。

要設(shè)置拖拽數(shù)據(jù)忿峻,使用setData()方法,接收兩個參數(shù)辕羽,數(shù)據(jù)類型和數(shù)據(jù)值:

event.dataTransfer.setData("text/plain", "拖拽的內(nèi)容");

如果要提供多種格式的數(shù)據(jù)逛尚,可以用不同的數(shù)據(jù)類型多次調(diào)用setData()方法。

const dt = event.dataTransfer;
dt.setData("application/x.bookmark", "bookmarkString");
dt.setData("text/uri-list", "http://www.mozilla.org");
dt.setData("text/plain", "http://www.mozilla.org");

如果需要以相同個數(shù)添加兩次數(shù)據(jù)刁愿,新數(shù)據(jù)會替換舊數(shù)據(jù)绰寞。使用clearData()方法清除這些數(shù)據(jù),它接收一個參數(shù)铣口,要刪除的數(shù)據(jù)類型克握。

event.dataTransfer.clearData("text/uri-list");

clearData()方法的參數(shù)type是可選的。如果未聲明type值枷踏,所有類型的數(shù)據(jù)都會被刪除菩暗。

反饋圖像

當(dāng)拖拽發(fā)生時,會生成拖拽元素的半透明圖像(觸發(fā)dragstart事件的元素)旭蠕,并且在拖拽過程中跟蹤鼠標(biāo)指針停团。這個圖像是自動創(chuàng)建的,不需要手動創(chuàng)建它掏熬。但是我們可以使用setDragImage()方法來自定義拖拽反饋圖像佑稠。

event.dataTransfer.setDragImage(image, xOffset, yOffset);
  • image是圖像的引用,通常是一個<img>元素旗芬,但是也可以是<canvas>或任何其他元素舌胶,也可以使用不在文檔中的圖像和畫布。生成的反饋圖像就是該圖像在屏幕上的樣子疮丛,以圖像原始大小繪制幔嫂。
  • xOffsetyOffset是圖像位置相對于鼠標(biāo)指針位置的偏移量誊薄。

注意:使用setDragImage()修改反饋圖像履恩,image元素必須存在于文檔中,如果不存在是不會生效的呢蔫,當(dāng)我們需要修改反饋圖像切心,實在沒辦法可以將反饋圖像在文檔中定位到視口以為的地方(但我不推薦)。我們可以用javascript創(chuàng)建image元素片吊。

示例1:修改拖動過程中的反饋圖像

效果1:將反饋圖像修改為<img>

[圖片上傳失敗...(image-c13a10-1690085058496)]

  <div
    id="dropBox"
    ondrop="drop(event)"
    ondragover="allowDrop(event)">
  </div>
  <br>
  <div
    id="dragBox"
    draggable="true"
    ondragstart="drag(event)">
    可以把我拖到矩形框中
  </div>

  <script>
    function allowDrop(ev) {
      ev.preventDefault();
    }
    function drag(ev) {
      let img = new Image();
      // img.src = "http://xxx.xx.drag.image"; // 方式1:外部圖片地址
      img.src = "./drag.jpg"; // 方式2:本地圖片
      ev.dataTransfer.setDragImage(img, 0, 0);
      ev.dataTransfer.setData("Text", ev.target.id);
    }
    function drop(ev) {
      ev.preventDefault();
      const data = ev.dataTransfer.getData("Text");
      ev.target.appendChild(document.getElementById(data));
    }
  </script>

效果2:將反饋圖像設(shè)置為canvas

[圖片上傳失敗...(image-134884-1690085058496)]

  <div
    id="dropBox"
    ondrop="drop(event)"
    ondragover="allowDrop(event)">
  </div>
  <br>
  <div
    id="dragBox"
    draggable="true"
    ondragstart="drag(event)">
    可以把我拖到矩形框中
  </div>
  <canvas style="position: absolute; top: -2999px; left: -2999px"></canvas>

  <script>
    function allowDrop(ev) {
      ev.preventDefault();
    }
    function drag(ev) {
      // 將反饋圖像設(shè)置為canvas
      var canvas = document.querySelector("canvas");
      
      canvas.width = 100;
      canvas.height = 50;

      let ctx = canvas.getContext("2d");
      ctx.fillStyle = "green";
      ctx.fillRect(10, 10, 200, 200);

      ev.dataTransfer.setData("Text", ev.target.id);
      ev.dataTransfer.setDragImage(canvas, 25, 25);
    }
    function drop(ev) {
      ev.preventDefault();
      const data = ev.dataTransfer.getData("Text");
      ev.target.appendChild(document.getElementById(data));
    }
  </script>

拖拽效果

拖拽過程中可能會執(zhí)行一些操作绽昏,給指定屬性設(shè)置不同的值,會影響到拖拽過程中瀏覽器顯示的鼠標(biāo)樣式

dragstart事件中可以設(shè)置effectAllowed屬性以指定允許拖拽源頭執(zhí)行三種操作中的哪幾種俏脊。默認(rèn)情況我們不需要修改該屬性全谤,除非特殊情況。

// 在dragstart事件中設(shè)置`effectAllowed`為`none`联予,表示不允許拖放操作
event.dataTransfer.effectAllowed = "none";
// 取值有
effectAllowed: none | copy | move | link | copyMove | copyLink | linkMove | all

在拖拽操作期間啼县,dragenterdragover事件的監(jiān)聽程序可以檢查effectAllowed屬性,以判定允許執(zhí)行哪些操作沸久。在dragenterdragover事件中我們可以設(shè)置dropEffect屬性季眷,來指定應(yīng)該執(zhí)行哪一個單項操作。

// 在`dragenter`或`dragover`事件中設(shè)置`dropEffect`為`none`
event.dataTransfer.dropEffect = "move";

dropEffect屬性用來控制拖放操作中用戶給予的反饋卷胯,會影響拖拽過程中瀏覽器顯示的鼠標(biāo)樣式子刮。

// 取值有
dropEffect: none | copy | link | move

drag 事件

drag事件中用戶拖動元素或選擇文本時,每隔幾百ms觸發(fā)一次窑睁。

// 可以使用`addEventListener()`方法或者`ondrag`
addEventListener('drag', (event) => {});

ondrag = (event) => { };

dragend 事件

dragend:當(dāng)拖拽操作結(jié)束時觸發(fā)(比如松開鼠標(biāo)按鍵或ESC按鍵)挺峡。

dragend事件無法被取消。

當(dāng)拖拽操作結(jié)束時担钮,在開始拖拽的目標(biāo)元素(可拖拽元素)上觸發(fā)dragend事件橱赠。不管拖拽是完成還是取消都會被觸發(fā)。dragend事件可以檢查dropEffect屬性的值來確認(rèn)拖拽是否成功箫津。

function dragend(ev) {
    console.log(ev.dataTransfer.dropEffect) // 如果值為none表示拖拽被取消
}

放置元素

內(nèi)容太多狭姨,就分兩個部分吧,下一部分介紹放置元素的相關(guān)內(nèi)容苏遥。
單擊此處查看HTML5拖放API第二部分

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饼拍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子田炭,更是在濱河造成了極大的恐慌师抄,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件教硫,死亡現(xiàn)場離奇詭異叨吮,居然都是意外死亡,警方通過查閱死者的電腦和手機瞬矩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門挤安,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丧鸯,你說我怎么就攤上這事蛤铜。” “怎么了丛肢?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵围肥,是天一觀的道長。 經(jīng)常有香客問我蜂怎,道長穆刻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任杠步,我火速辦了婚禮氢伟,結(jié)果婚禮上榜轿,老公的妹妹穿的比我還像新娘。我一直安慰自己朵锣,他們只是感情好谬盐,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诚些,像睡著了一般飞傀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诬烹,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天砸烦,我揣著相機與錄音,去河邊找鬼绞吁。 笑死幢痘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的家破。 我是一名探鬼主播雪隧,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼员舵!你這毒婦竟也來了脑沿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤马僻,失蹤者是張志新(化名)和其女友劉穎庄拇,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體韭邓,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡措近,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了女淑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞭郑。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鸭你,靈堂內(nèi)的尸體忽然破棺而出屈张,到底是詐尸還是另有隱情,我是刑警寧澤袱巨,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布阁谆,位于F島的核電站,受9級特大地震影響愉老,放射性物質(zhì)發(fā)生泄漏场绿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一嫉入、第九天 我趴在偏房一處隱蔽的房頂上張望焰盗。 院中可真熱鬧璧尸,春花似錦、人聲如沸熬拒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梦湘。三九已至,卻和暖如春件甥,著一層夾襖步出監(jiān)牢的瞬間捌议,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工引有, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瓣颅,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓譬正,卻偏偏與公主長得像宫补,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子曾我,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 前言 拖放(drap && drop)在我們平時的工作中粉怕,經(jīng)常遇到。它表示:抓取對象以后拖放到另一個位置抒巢。目前贫贝,它...
    weiqinl閱讀 1,354評論 0 3
  • html5出現(xiàn)了很多比較好的應(yīng)用,今天我們來講講關(guān)于元素拖動的蛉谜。 前言 關(guān)于拖動稚晚,我們應(yīng)該理解什么是拖動源和放置目...
    儂姝沁兒閱讀 1,243評論 0 5
  • 拖放事件 拖放操作是將一個元素拖放到另一個元素的操作,這項操作涉及到兩個元素:被拖放元素和放置元素型诚。在拖放過程中客燕,...
    柏丘君閱讀 624評論 0 0
  • 拖放(Drag 和 drop)是HTML5標(biāo)準(zhǔn)的組成部分 拖放 拖放是一種常見的特性,即抓取對象以后拖放到其他位置...
    趙晨敏閱讀 613評論 0 0
  • 提到拖拽狰贯,我們都很熟悉也搓,那么拖放呢?一字之差涵紊,代表的意義是不一樣的还绘,拖拽就是拉著走,拖放就是有拖栖袋,有放拍顷,我們都知道...
    千鋒H5閱讀 547評論 0 0