011 HTML5 拖放事件 01

拖放事件

拖放操作是將一個元素拖放到另一個元素的操作擦剑,這項操作涉及到兩個元素:被拖放元素和放置元素澜倦。在拖放過程中仇参,被拖放元素會經(jīng)歷以下幾個事件:

  • dragstart
  • drag
  • dragend

當我們將被拖放元素拖動到放置元素(目標元素)時咧纠,會經(jīng)歷以下幾個事件:

  • dragenter
  • dragover
  • dropdragleave

其中,drop 事件在被拖放元素放置到目標元素上時觸發(fā)秽澳,dropleave 事件在被拖放元素離開目標時觸發(fā)闯睹。

觸發(fā) drop 事件

默認情況下,某些元素是不允許放置目標的(如 div)担神,在這些元素上楼吃,無法觸發(fā) drop 事件,但是能觸發(fā)dragenterdragoverdragleave三個事件孩锡】嵯看個例子:

...
<style>
    img{
        width: 100px;
        height: 100px;
        border:10px solid orange;
    }
    #box{
        width: 200px;
        height: 200px;
        background-color:bisque;
        margin:50px auto;
    }
</style>
...
<body>
    ![](./01.png)
    <div id="box"></div>
</body>
...
<script>
    img.addEventListener("dragstart",(e)=>{
        console.log("拖動開始")
    })

    box.addEventListener("dragenter",(e)=>{
        console.log("觸發(fā) dragenter 事件")
    })

    box.addEventListener("dragover",(e)=>{
        console.log("觸發(fā) dragover 事件")
    })

    box.addEventListener("drop",(e)=>{
        console.log("觸發(fā) drop 事件")
    })
   
    box.addEventListener("dragleave",(e)=>{
        console.log("觸發(fā) dragleave 事件")
    })
</script>
...

運行效果:

拖放事件1.gif

可見,默認情況下是無法觸發(fā) drop 事件的浮创,并且將拖放元素放到目標元素上時還會觸發(fā)目標元素的 dragleave 事件忧吟。
如果我們想觸發(fā)目標元素的 drop 事件,需要阻止目標元素的 dragenterdragover 事件的默認行為斩披。

...
box.addEventListener("dragenter",(e)=>{
        console.log("觸發(fā) dragenter 事件")
        e.preventDefault();
    })

    box.addEventListener("dragover",(e)=>{
        console.log("觸發(fā) dragover 事件")
        e.preventDefault();
    })
...

運行效果如下:

拖放事件2.gif

可見,阻止目標元素dragenterdragover 事件的默認行為后讹俊,可以正常觸發(fā) drop 事件了垦沉,同時,當把拖放元素放到目標元素上時仍劈,不會再觸發(fā)dragleave 事件了厕倍。

消息傳遞

在拖放操作時,可能需要進行數(shù)據(jù)的傳遞贩疙,典型的如拖放的購物車功能讹弯,需要將商品信息傳遞到購物車列表中,這就需要消息傳遞了这溅。
拖拽事件的事件對象中有一個 dataTransfer 屬性组民,可以利用該屬性來傳遞和接受消息:

  • dataTransfer.setData(key,value):用來防止消息
  • dataTransfer.getData(key):用來獲取消息

需要注意的是,dataTransfer.getData 這個方法悲靴,只有在 drop 事件中才能獲取到數(shù)據(jù)臭胜,在其他事件中是獲取不到數(shù)據(jù)的。
將上面的例子簡單修改一下:

let flag = 1;
let goodsList = [];
img.addEventListener("dragstart",(e)=>{
    e.dataTransfer.setData("item",`商品${flag++}`)
})

box.addEventListener("dragenter",(e)=>{
    e.preventDefault();
})

box.addEventListener("dragover",(e)=>{
    e.preventDefault();
})

box.addEventListener("drop",(e)=>{
    const goodsInfo = e.dataTransfer.getData("item");
    goodsList.push(goodsInfo)
    console.log(`已有${goodsList.length}件商品了`)
    box.innerHTML = goodsList.length;
})

運行效果:

拖放事件3.gif

控制光標樣式

dataTransfer 這個屬性除了可以用來傳遞消息之外癞尚,還可以規(guī)定被拖動元素和目標元素的行為耸三,其中,被拖動元素的行為由 dataTransfereffectAllowed 屬性控制浇揩,目標元素的行為由 dataTransferdropEffect 屬性控制仪壮。
其中,effectAllowed 屬性必須在拖放元素的 dragstart 事件中設(shè)置胳徽,dropEffect 屬性必須在目標元素的 dragenter 事件中設(shè)置积锅。
另外,effectAllowed 需要和 dragEffect 搭配使用膜廊。
其中乏沸,effectAllowed 屬性可以設(shè)置以下幾個值:

"none":不能把拖動的元素放在這里。這是除文本框之外所有元素的默認值爪瓜。
"move":應(yīng)該把拖動的元素移動到放置目標蹬跃。
"copy":應(yīng)該把拖動的元素復(fù)制到放置目標。
"link":表示放置目標會打開拖動的元素(但拖動的元素必須是一個鏈接,有 URL)蝶缀。

dropEffect 屬性可以設(shè)置以下幾個值:

"uninitialized":沒有給被拖動的元素設(shè)置任何放置行為丹喻。
"none":被拖動的元素不能有任何行為。
"copy":只允許值為"copy"的 dropEffect翁都。
"link":只允許值為"link"的 dropEffect碍论。
"move":只允許值為"move"的 dropEffect。
"copyLink":允許值為"copy"和"link"的 dropEffect柄慰。
"copyMove":允許值為"copy"和"move"的 dropEffect鳍悠。
"linkMove":允許值為"link"和"move"的 dropEffect。
"all":允許任意 dropEffect坐搔。

以上引用自 《JavaScript 高級程序設(shè)計(第三版)》藏研。
需要注意的是:設(shè)置 effectAlloweddropEffect 屬性只能改變光標的樣式,但不會對真實的 DOM 節(jié)點進行復(fù)制或移動等操作概行。如果你需要對真實的 DOM 進行移動或復(fù)制操作蠢挡,還需要自己去實現(xiàn)。

setDragImage 方法

該方法也是 dataTransfer 屬性上的一個方法凳忙,用來設(shè)置拖放元素時顯示在光標下的圖像业踏,該方法的使用方式如下:

dataTransfer.setDragImage(element,xpos,ypos);

其中 element 參數(shù)是顯示在鼠標下的元素,xposypos 分別是鼠標相對于元素的坐標涧卵。
將前面的例子做一些修改勤家,看下運行效果:

...
<style>
    img{
        width: 100px;
        height: 100px;
        border:10px solid orange;
    }
    #box{
        width: 200px;
        height: 200px;
        background-color:bisque;
        margin:50px auto;
    }
    #dragImg{
        width: 100px;
        height: 100px;
        background:red;
        border-radius: 50%;
        opacity: 0;
    }
</style>
...
<body>
    ![](./01.png)
    <div id="box"></div>
    <div id="dragImg"></div>
</body>
...
<script>
    img.addEventListener("dragstart",(e)=>{
        if(Math.random() > 0.5){
            e.dataTransfer.setDragImage(dragImg,0,0);
            dragImg.style.opacity = 1;
        }else{
            e.dataTransfer.setDragImage(img,0,0);
        }
    })

    box.addEventListener("dragenter",(e)=>{
        e.preventDefault();
    })

    box.addEventListener("dragover",(e)=>{
        e.preventDefault();
    })
</script>
...

運行效果:

拖放事件4.gif

上面的代碼使用兩個元素進行了對比,在實際用途中艺演,這個方法還是很有用的却紧,可以用來設(shè)置拖放時鼠標指針下的背景圖像(元素)以及位置,方便我們進行定制胎撤。

使任意元素可拖動

默認情況下晓殊,只有圖片、鏈接和文本是可以拖動的伤提,要想使其他的元素可拖動巫俺,只需設(shè)置元素的 draggable 屬性為 true 即可。

總結(jié)

本文主要介紹了 HTML5 中的拖放事件肿男,包括:

  • 被拖放元素和目標元素的幾個對應(yīng)事件
  • 如何阻止默認行為從而可以觸發(fā) drop 事件
  • 如何使用 dataTransfer 傳遞消息
  • 如何使用 effectAlloweddropEffect 控制光標樣式
  • 如何使用 setDragImage() 方法設(shè)置拖放時的背景圖像
  • 如何使任意元素可拖動

關(guān)于拖放事件介汹,還剩下一點內(nèi)容,主要是文件相關(guān)的操作(拖放上傳文件)舶沛。鑒于篇幅嘹承,將拖放事件拆成兩篇,下篇內(nèi)容主要寫和文件相關(guān)的一些操作如庭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末叹卷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌骤竹,老刑警劉巖帝牡,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蒙揣,居然都是意外死亡靶溜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門懒震,熙熙樓的掌柜王于貴愁眉苦臉地迎上來罩息,“玉大人,你說我怎么就攤上這事个扰】弁簦” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵锨匆,是天一觀的道長。 經(jīng)常有香客問我冬筒,道長恐锣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任舞痰,我火速辦了婚禮土榴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘响牛。我一直安慰自己玷禽,他們只是感情好,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布呀打。 她就那樣靜靜地躺著矢赁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贬丛。 梳的紋絲不亂的頭發(fā)上撩银,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機與錄音豺憔,去河邊找鬼额获。 笑死,一個胖子當著我的面吹牛恭应,可吹牛的內(nèi)容都是我干的抄邀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼昼榛,長吁一口氣:“原來是場噩夢啊……” “哼境肾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤准夷,失蹤者是張志新(化名)和其女友劉穎钥飞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衫嵌,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡读宙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了楔绞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片结闸。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖酒朵,靈堂內(nèi)的尸體忽然破棺而出桦锄,到底是詐尸還是另有隱情,我是刑警寧澤蔫耽,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布结耀,位于F島的核電站,受9級特大地震影響匙铡,放射性物質(zhì)發(fā)生泄漏图甜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一鳖眼、第九天 我趴在偏房一處隱蔽的房頂上張望黑毅。 院中可真熱鬧,春花似錦钦讳、人聲如沸矿瘦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缚去。三九已至,卻和暖如春掘猿,著一層夾襖步出監(jiān)牢的瞬間病游,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工稠通, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衬衬,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓改橘,卻偏偏與公主長得像滋尉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子飞主,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

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