網(wǎng)站網(wǎng)頁設(shè)計(jì)要求真正免費(fèi)的網(wǎng)站建站平臺(tái)運(yùn)營
最近碰到了個(gè)需求,大概就是要通過可視化拖拽的方式配置一個(gè)冰柜,需要把預(yù)設(shè)好的冰柜內(nèi)部架子模板一個(gè)個(gè)拖到冰箱內(nèi)。一開始的想法是用鼠標(biāo)事件(mousedown、mouseup等)那一套去實(shí)現(xiàn),能實(shí)現(xiàn)但是過程過于復(fù)雜,需要控制的狀態(tài)太多了。其實(shí)
Web Api
為 html 元素拖拽量身定制了一套HTML
拖放API
,用這個(gè)方法實(shí)現(xiàn)一些簡單的拖拽功能簡直不要太簡單。為此寫了這篇文章,下面將詳細(xì)介紹HTML 拖放 API
的核心知識(shí)點(diǎn)
文檔
一、被拖拽元素和放置被拖拽元素的元素
通常我們所了解的拖放是按住鼠標(biāo)左鍵不放然后移動(dòng)鼠標(biāo)把一個(gè)頁面元素從某個(gè)位置移動(dòng)到另一個(gè)位置,然后松開鼠標(biāo)左鍵,至此完成了整個(gè)拖放過程。在這個(gè)過程中我們需要先重點(diǎn)關(guān)注兩個(gè)東西,一個(gè)是
被拖拽元素
另一個(gè)是放置被拖拽元素的元素
。
1.1 被拖拽元素
我們得先有個(gè)概念,頁面上顯示的元素默認(rèn)并不都是可以被拖拽的(除了圖片、被選中的文字、鏈接),所以如果當(dāng)前元素默認(rèn)不可被拖拽那么就得先把它設(shè)置為可拖拽的。ps:可拖拽元素被拖拽時(shí)會(huì)有一個(gè)半透明的快照跟著鼠標(biāo)移動(dòng)。
將 HTML 元素的 draggable 屬性設(shè)置為 true, 元素就可以變?yōu)榭赏献г亍PЧ缦聢D。
<div id="box" draggable="true">draggable box</div>
1.2 可放置被拖拽元素的元素
所有的元素區(qū)域默認(rèn)是不支持放置被拖拽元素的,直觀的表現(xiàn)是,當(dāng)被拖拽元素經(jīng)過不可放置區(qū)域時(shí)鼠標(biāo)的樣式是一個(gè)禁止放置的一個(gè)圖標(biāo)(圓圈帶一個(gè)斜杠),所以需要將目標(biāo)元素設(shè)置為一個(gè)可放置區(qū)域
默認(rèn)情況下是這樣:
<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置區(qū)域</div>
設(shè)置為放置區(qū)域需要給元素綁定一個(gè)事件 dragover 且要 阻止默認(rèn)行為
<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置區(qū)域</div>
<script>let dropDom = document.getElementById('droppable')dropDom.addEventListener('dragover', (e) => {e.preventDefault()})
</script>
React:
放置區(qū)域
需要綁定onDragOver
事件,且要 阻止默認(rèn)行為 – 其他事件一樣加on
<div draggable="true">draggable box</div>
<div onDragOver={(e) => {e.preventDefault()}}>放置區(qū)域</div>
設(shè)置為可放置區(qū)域后鼠標(biāo)樣式也變了不再是禁止圖標(biāo),而是一個(gè)加號(hào)圖標(biāo)(圖標(biāo)可以設(shè)置,下面會(huì)講解):
然而你會(huì)發(fā)現(xiàn)被拖放元素并沒有真正的被放置到放置區(qū)域,這是必然的,放置操作需要開發(fā)者自行定義
,以上的設(shè)置只是是為了向用戶表明這個(gè)區(qū)域是允許放東西的,那么至于怎么放需要開發(fā)者自行決定。
二、拖拽過程觸發(fā)的一些事件
這一小節(jié)將帶你了解整個(gè)拖放過程的其他細(xì)節(jié),比如拖拽過程中會(huì)觸發(fā)哪些事件
2.1 被拖放目標(biāo)觸發(fā)的事件
給被拖放目標(biāo)元素綁定三個(gè)事件 dragstart、drag、dragend。
<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置區(qū)域</div>
<script>let dragDom = document.getElementById('box')dragDom.addEventListener('dragstart', (e) => {console.log('開始拖動(dòng)');})dragDom.addEventListener('drag', (e) => {console.log('拖動(dòng)中');})dragDom.addEventListener('dragend', (e) => {console.log('結(jié)束拖動(dòng)');})
</script>
React
<div draggable="true"onDragStart={(e) => {console.log("開始拖動(dòng)", e);}}onDrag={(e) => {console.log("拖動(dòng)中", e);}}onDragEnd={(e) => {console.log("結(jié)束拖動(dòng)", e);}}
>
>draggable box</div>
<div onDragOver={(e) => {e.preventDefault()}}>放置區(qū)域</div>
開始拖動(dòng)觸發(fā) dragstart
,拖動(dòng)過程中(鼠標(biāo)不松開)觸發(fā)drag
,松開鼠標(biāo)(或者按下 Esc
鍵)觸發(fā) dragend
。
2.2 被拖拽元素在放置區(qū)域內(nèi)會(huì)觸發(fā)的事件
先給放置目標(biāo)元素綁定四個(gè)事件
<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置區(qū)域</div>
<script>let dropDom = document.getElementById('droppable')dropDom.addEventListener('dragenter', (e) => {console.log('進(jìn)入到了放置區(qū)域~');})dropDom.addEventListener('dragover', (e) => {e.preventDefault()console.log('在放置區(qū)域內(nèi)拖拽中~');})dropDom.addEventListener('dragleave', (e) => {console.log('離開了放置區(qū)域~');})dropDom.addEventListener('drop', (e) => {console.log('在放置區(qū)域內(nèi),放下了被拖拽元素~')})
</script>
拖拽元素進(jìn)入放置區(qū)域內(nèi)時(shí)觸發(fā) dragenter
事件,在放置區(qū)域內(nèi)移動(dòng)被拖放(鼠標(biāo)不松開)元素觸發(fā) dragover
事件,被拖放元素離開放置區(qū)域觸發(fā) dragleave
事件,在放置區(qū)域內(nèi)松開鼠標(biāo)觸發(fā) drop
事件。
三、實(shí)現(xiàn)真正意義上的元素拖放
通過上面觸發(fā)的事件我們可以知道,用戶真正在放置區(qū)域釋放鼠標(biāo)的時(shí)候只有 drop 事件能夠監(jiān)聽到。所以開發(fā)者需要在這個(gè)事件里做真正的放置操作,放置什么由開發(fā)者決定,可以是被拖拽元素,也可以是自定義的一些內(nèi)容。
放置被拖拽元素:
<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置區(qū)域</div>
<script>let dropDom = document.getElementById('droppable')dropDom.addEventListener('dragover', (e) => {e.preventDefault()console.log('在放置區(qū)域內(nèi)拖拽中~');})dropDom.addEventListener('drop', (e) => {console.log('在放置區(qū)域內(nèi),放下了被拖拽元素~')e.target.appendChild(document.getElementById('box'))})
</script>
放置自定義內(nèi)容
dropDom.addEventListener('drop', (e) => {console.log('在放置區(qū)域內(nèi),放下了被拖拽元素~')let customCOntent = '<p>自定義內(nèi)容</p>'e.target.innerHTML = e.target.innerHTML + customCOntent
})
四、dataTransfer 對(duì)象
4.1 從被拖放元素向可放置元素傳遞數(shù)據(jù)
dataTransfer
對(duì)象提供了一個(gè)setData()
方法,它接受兩個(gè)參數(shù),第一個(gè)參數(shù)是傳遞數(shù)據(jù)的類型(一般是標(biāo)準(zhǔn)的MIME類型
),第二個(gè)數(shù)據(jù)是數(shù)據(jù)值。dataTransfer
還提供了getData()
的方法用于獲取傳遞的數(shù)據(jù),它接受一個(gè)參數(shù),參數(shù)值為setData
對(duì)應(yīng)的第一個(gè)參數(shù)。
傳遞一個(gè)簡單的字符串?dāng)?shù)據(jù)
<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置區(qū)域</div>
<script>let dropDom = document.getElementById('droppable')let dragDom = document.getElementById('box')dragDom.addEventListener('dragstart', (e) => {e.dataTransfer.setData('text/plain', '自定義數(shù)據(jù)')})dropDom.addEventListener('dragover', (e) => {e.preventDefault()})dropDom.addEventListener('drop', (e) => {let data = e.dataTransfer.getData('text/plain')console.log('你傳遞的數(shù)據(jù)為:', data);})
</script>
?注意:只能在 dragstart 事件中設(shè)置數(shù)據(jù),在其他地方設(shè)置無效。且只能在 drop 事件中獲取設(shè)置的數(shù)據(jù),其他事件中獲取不到。
案例:根據(jù)傳遞的數(shù)據(jù)放置不同的內(nèi)容。
<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置區(qū)域</div>
<script>let dropDom = document.getElementById('droppable')let dragDom = document.getElementById('box')dropDom.addEventListener('dragover', (e) => {e.preventDefault()})dropDom.addEventListener('drop', (e) => {let num = e.dataTransfer.getData('num')console.log(num);if(num > 5)e.target.innerHTML = e.target.innerHTML + '<p>傳遞的數(shù)字大于5</p>'else if(num == 5) e.target.innerHTML = e.target.innerHTML + '<p>傳遞的數(shù)字等于5</p>'elsee.target.innerHTML = e.target.innerHTML + '<p>傳遞的數(shù)字小于5</p>'})dragDom.addEventListener('dragstart', (e) => {let num = Math.floor(Math.random() * 10) + 1;e.dataTransfer.setData('num', num)})
</script>
4.2 自定義拖拽過程中跟隨鼠標(biāo)移動(dòng)的內(nèi)容
默認(rèn)情況下元素被拖拽時(shí)會(huì)有一個(gè)半透明的元素快照跟隨著鼠標(biāo)移動(dòng)。通過 dataTransfer 提供的 setDragImage(elemnt, xOffset, yOffset) 方法是可以自定義跟隨內(nèi)容。接受三個(gè)參數(shù) elemnt 可以是 dom 節(jié)點(diǎn)或者一個(gè)圖片對(duì)象,xOffset, yOffset 是相對(duì)于鼠標(biāo)的偏移量。
語法
dataTransfer.setDragImage(img, xOffset, yOffset);
img | Element
用于拖曳反饋圖像的圖像 Element 元素。
如果 Element 是一個(gè) img 元素,則將拖動(dòng)位圖設(shè)置為該元素的圖像(保持大小);否則,將拖動(dòng)數(shù)位圖設(shè)置為從給定元素所生成的圖片
xOffset
使用 long 指示相對(duì)于圖片的橫向偏移量
yOffset
使用 long 指示相對(duì)于圖片的縱向偏移量
解析
- 發(fā)生拖動(dòng)時(shí),從拖動(dòng)目標(biāo) (
dragstart
事件觸發(fā)的元素) 生成半透明圖像,并在拖動(dòng)過程中跟隨鼠標(biāo)指針。這個(gè)圖片是自動(dòng)創(chuàng)建的,你不需要自己去創(chuàng)建它。然而,如果想要設(shè)置為自定義圖像,那么DataTransfer.setDragImage()
方法就能派上用場(chǎng)。 - 圖像通常是一個(gè)
<image>
元素,但也可以是<canvas>
或任何其他圖像元素。該方法的 x 和 y 坐標(biāo)是圖像應(yīng)該相對(duì)于鼠標(biāo)指針出現(xiàn)的偏移量。
坐標(biāo)指定鼠標(biāo)指針相對(duì)于圖片的偏移量。例如,要使圖像居中,請(qǐng)使用圖像寬度和高度的一半。通常在dragstart
事件處理程序中調(diào)用此方法。
實(shí)際用例
setDragImage 的第一個(gè)參數(shù)接受的是一個(gè)Element參數(shù),這樣的話,普通的
html元素
、image元素
、canvas
都可以傳遞
1、設(shè)置為一個(gè)圖片:
<script>import Tag from "../../style/imgs/attributeTag/路徑.png"; //已經(jīng)存在的圖片let dragDom = document.getElementById('box')dragDom.addEventListener('dragstart', (e) => {let img = new Image()// 創(chuàng)建一個(gè)圖像并且使用它作為拖動(dòng)圖像// 請(qǐng)注意: 改變 "example.gif" 為一個(gè)已經(jīng)存在的圖片// 或者,一個(gè)還沒有創(chuàng)建出來的圖片,那么瀏覽器將會(huì)使用默認(rèn)的拖動(dòng)圖片// 譯者注:默認(rèn)的拖動(dòng)圖片與拖動(dòng)對(duì)象沒有聯(lián)系。一般是一個(gè)小型文件圖標(biāo)// 例如:// mg.src = Tag //或// mg.src = `data:image/png;base64,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`;img.src = 'example.gif'e.dataTransfer.setDragImage(img, 10, 10)})
</script>
2、以官網(wǎng)例子為例,把canvas作為參數(shù)傳遞,我首先嘗試的是這種方式,發(fā)現(xiàn)并不能生效
。(官方
的例子沒有
運(yùn)行成功)
function dragWithCustomImage(event) {var canvas = document.createElementNS("http://www.w3.org/1999/xhtml","canvas");canvas.width = canvas.height = 50;var ctx = canvas.getContext("2d");ctx.lineWidth = 4;ctx.moveTo(0, 0);ctx.lineTo(50, 50);ctx.moveTo(0, 50);ctx.lineTo(50, 0);ctx.stroke();var dt = event.dataTransfer;dt.setData('text/plain', 'Data to Drag');dt.setDragImage(canvas, 25, 25);
}
3、根據(jù)案例,我接著使用·HtmlDivElement·作為參數(shù)傳遞,創(chuàng)建了·DIV元素·,此時(shí)也·沒有生效·。
export function drawDragImage(dataTransfer: DataTransfer, context: string) {
const drawItem: API.EquipmentInfo = JSON.parse(context);
const div = document.createElement(‘div’);
div.style.height = itemObj.height + ‘px’;
div.style.width = itemObj.width + ‘px’;
div.style.border = ‘1px solid #000’;
const span = document.createElement(‘span’);
span.innerText = ‘2222’;
div.appendChild(span);
dataTransfer.setDragImage(div, drawItem.width / 2, drawItem.height / 2);
}
4、然后,我改進(jìn)了canvas
,把canvas轉(zhuǎn)化為圖片,第一次拖拽的時(shí)候,因?yàn)閕mage加載元素是異步導(dǎo)致了沒有生效,如圖1;第二以后拖拽的時(shí)候可以生效,如圖二
。
const imageContent = canvas.toDataURL('image/jpeg', 1);const image = new Image();image.src = imageContent;image.onload = () => {console.log('image2 load');};dataTransfer.setDragImage(image, drawItem.width / 2, drawItem.height / 2);
5、最后我嘗試了使用官網(wǎng)的方法,同樣因?yàn)?code>image加載圖片是異步的,而拖拽
事件是同步發(fā)生
的,導(dǎo)致了第一次執(zhí)行失敗
。
function dragstart_handler(ev) {console.log("dragStart");// 設(shè)置拖動(dòng)的格式和數(shù)據(jù)。使用事件目標(biāo)的 id 作為數(shù)據(jù)ev.dataTransfer.setData("text/plain", ev.target.id);// 創(chuàng)建一個(gè)圖像并且使用它作為拖動(dòng)圖像// 請(qǐng)注意:改變 "example.gif" 為一個(gè)已經(jīng)存在的圖片// 或者,一個(gè)還沒有創(chuàng)建出來的圖片,那么瀏覽器將會(huì)使用默認(rèn)的拖動(dòng)圖片// 譯者注:默認(rèn)的拖動(dòng)圖片與拖動(dòng)對(duì)象沒有聯(lián)系。一般是一個(gè)小型文件圖標(biāo)var img = new Image();img.src = 'example.gif';ev.dataTransfer.setDragImage(img, 10, 10);
}
解決方案
在嘗試了不同方式設(shè)置拖拽反饋圖像,總結(jié)了一些解決方案
:
- 以html頁面的元素為模版,動(dòng)態(tài)生成內(nèi)容,然后設(shè)置
Element元素參數(shù)
,可以設(shè)置DIV元素的z-index
(使用z-index,必須使用position:relative | absolute
)–(嘗試使用過css1、position:absolute
定位出瀏覽器可視界面 2、display:none
無用),隱藏在實(shí)際頁面之下:這樣可以動(dòng)態(tài)生成要拖拽的元素,并和生成的fabric的group保持一致。 完美的解決了問題 。
js
export function drawDragImage(dataTransfer: DataTransfer, context: string) {const drawItem: API.EquipmentInfo = JSON.parse(context);const dragElement = document.getElementById('dragItem');const idElement = dragElement?.getElementsByClassName('dragItemId')[0];const nameElement = dragElement?.getElementsByClassName('dragItemName')[0];if (idElement) {idElement.innerHTML = drawItem.id;}if (nameElement) {nameElement.innerHTML = drawItem.typeName || '';}if (dragElement) {dragElement.style.height = drawItem.height + 'px';dragElement.style.width = drawItem.width + 'px';dragElement.style.border = '1px solid #000';dragElement.style.background = '#fff';}if (dragElement) {dataTransfer.setDragImage(dragElement, drawItem.width / 2, drawItem.height / 2);}}
React
import {useRef} from "react";import { Modal, Space, Input, Tree, Button, Badge } from "antd";const mouseStyle = useRef<any>(null);<divdraggable="true"onDragStart={(e) => {//mouseStyle.currente.dataTransfer.setDragImage(mouseStyle.current, 10, 10);}}>移動(dòng)位置</div>//
//absolute top-[10%] z-[1] h-10 css使用了tailwindcss
//npm install -D tailwindcss
//https://tailwindcss.com/docs/installation 文檔地址<div className="absolute top-[10%] z-[1] h-10" ref={mouseStyle}><Badge count={5}><div className=" border border-[#444444] leading-6 h-6 w-15">2023.09.22初級(jí)會(huì)計(jì)資格考試</div></Badge>
</div>
4.3 設(shè)置放置前的反饋圖標(biāo)
dataTransfer 提供了一個(gè)
dropEffect
屬性設(shè)置放置前的反饋圖標(biāo),它有四種取值 none move copy link
在 dragover 中設(shè)置 dropEffect
的值
dropDom.addEventListener('dragover', (e) => {e.preventDefault()e.dataTransfer.dropEffect = 'link' // none || move || copy || link
})
- 值為 none 或者經(jīng)過不可放置區(qū)域,顯示禁止放置圖標(biāo)
- 值為 move 時(shí)
- 值為 copy 時(shí)
- 值為 link 時(shí)
4.4 拖動(dòng)文件上傳
通過 dataTransfer 的
files
屬性可以獲取用戶拖拽的文件信息
拖拽系統(tǒng)文件到放置區(qū)域,并打印拖拽的文件信息:
dropDom.addEventListener('drop', (e) => {e.preventDefault()// 上傳的文件列表let fileList = e.dataTransfer.filesfor (let i = 0; i < fileList.length; i++) {const file = fileList[i];console.log('文件名:' + file.name);console.log('文件大小:' + file.size);// 后續(xù)操作 比如:調(diào)接口上傳文件}
})
4.5 清除 setData() 的值
dataTransfer 提供了
clearData()
清除 setData 設(shè)置的值,傳參數(shù)則刪除指定類型的值,不傳則全部清除。
dropDom.addEventListener('drop', (e) => {console.log(e.dataTransfer.getData('text/plain'));console.log(e.dataTransfer.getData('text/html'));
})dragDom.addEventListener('dragstart', (e) => {e.dataTransfer.setData('text/plain', '自定義數(shù)據(jù)')e.dataTransfer.setData('text/html', '自定義數(shù)據(jù)2')e.dataTransfer.clearData('text/html')
})
4.6 查看設(shè)置了哪些類型的值
dataTransfer 提供了
types
屬性查看 setData 設(shè)置了哪些類型的值。
dropDom.addEventListener('drop', (e) => {console.log(e.dataTransfer.types);
})
dragDom.addEventListener('dragstart', (e) => {e.dataTransfer.setData('text/plain', '自定義數(shù)據(jù)')e.dataTransfer.setData('text/html', '自定義數(shù)據(jù)2')
})
4.7 effectAllowed 屬性取值會(huì)影響到 dropEffect 的取值效果。
effectAllowed 用于限制 dropEffect 只能設(shè)置哪些值
effectAllowed 的取值有: + none -> 此項(xiàng)表示 dropEffect 設(shè)置任何值都是禁止效果 + copy -> dropEffect 可以設(shè)置為 copy + copyLink -> dropEffect 可以設(shè)置為 copy 和 link + copyMove -> dropEffect 可以設(shè)置為 copy 和 Move + link -> dropEffect 可以設(shè)置為 link + linkMove -> dropEffect 可以設(shè)置為 link 和 Move + move -> dropEffect 可以設(shè)置為 Move + all -> dropEffect 可以設(shè)置為所有合法值 + uninitialized -> 等同 all 效果
dropDom.addEventListener('dragover', (e) => {e.preventDefault()e.dataTransfer.dropEffect = 'move'
})
dragDom.addEventListener('dragstart', (e) => {e.dataTransfer.effectAllowed = 'none'
})
上面即使 dropEffect 設(shè)置為 move, 但是 effectAllowed 的值為 none,所有還是禁止放置的反饋圖標(biāo)。
五、總結(jié)
- 實(shí)現(xiàn)一個(gè)拖拽功能時(shí)先定義好被拖拽元素和放置區(qū)域元素。
- 所有的放置操作都是在 drop 事件中完成。
- 放置前的反饋效果可以根據(jù)你傳遞的數(shù)據(jù)來設(shè)置 dropEffect 顯示不同的效果。
- 被拖拽元素也可以是放置區(qū)域,放置區(qū)域也可以是被拖拽元素,兩者沒有明確的界限。
- 功能自定義按需求開發(fā)