title | date | author | categories | tags | summary | |
---|---|---|---|---|---|---|
drag |
2022-03-28 09:59:44 -0700 |
Jack-zhang |
JS |
|
html中的元素拖放操作 |
该属性是一个全局属性。是枚举类型,用于表示元素是否允许使用拖放操作
true
:可以拖动false
:禁止拖动auto
:跟随浏览器定义是否可以拖动
<div draggable="true"></div>
拖放(
Drag
和Drop
)接口使应用能够在浏览器使用拖放功能,并且继承了 DOM 事件模型以及从 mouse 事件继承而来,得到 drag 事件。
DragEvent
的所有事件都是全局事件
//可以直接在document上使用
document.addEventListener(
"drag", function (event) {
console.log(event.target)
})
- 在操作期间,有一些事件的类型可能会被多次触发(例如
drag
和dragover
)
事件 | On型事件处理程序 | 触发时刻 |
---|---|---|
dragstart | ondragstart | 当用户开始拖拽一个元素或选中的文本时触发 |
drag | ondrag | 当拖拽元素或选中的文本时触发或者到达可放置区域触发 |
dragend | ondragend | 当拖拽操作结束时触发(比如松开鼠标按键或敲 Esc 键) |
dragexit | ondragexit | 当元素变得不再是拖拽操作的选中目标时触发(官网并没有详细说明) |
dragenter | ondragenter | 当拖拽元素或选中的文本刚进入到一个可释放目标时触发 |
dragover | ondragover | 当元素或选中的文本被拖入到一个可释放目标内时触发(每 100 毫秒触发一次) |
dragleave | ondragleave | 当拖拽元素或选中的文本离开一个可释放目标时触发 |
drop | ondrop | 当元素放置在可放置区域时触发(此时可以取消浏览器的默认行为) |
-
被拖动的元素事件有:
drag
、dragstart
、dragend
、dragexit
-
目的地对象事件有:
dragenter
、dragover
、dragleave
、drop
-
dragenter
和dragover
事件的默认行为是拒绝接受任何被拖放的元素。- 需要使用
event.preventDefault()
阻止默认行为
- 需要使用
-
默认触发的顺序就是:
dragstart->dragenter->dragleave->dragend
<style>
.box {
width: 100px;
height: 100px;
background-color: rgb(153, 80, 202);
}
.container {
width: 400px;
height: 400px;
margin: 100px auto;
border: 3px solid rgb(40, 180, 127);
}
</style>
<body>
<div class="box" draggable="true"></div>
<div class="container"></div>
</body>
<script>
const box = document.getElementsByClassName("box")[0];
const container = document.getElementsByClassName("container")[0];
box.addEventListener("drag", function (e) {
//console.log(e.target, "drop")
})
box.addEventListener("dragstart", function (e) {
console.log(e.target, "dragstart")
})
box.addEventListener("dragend", function (e) {
console.log(e.target, "dragend")
})
box.addEventListener("dragexit", function (e) {
console.log(e.target, "dragexit")
})
container.addEventListener("dragenter", function (e) {
e.preventDefault()
console.log(e.target, "dragenter")
})
container.addEventListener("dragover", function (e) {
//e.preventDefault()
//console.log(e.target, "dragover")
})
container.addEventListener("dragleave", function (e) {
console.log(e.target, "dragleave")
})
</script>
DataTransfer()
是一个构造函数,返回一个新的DataTransfer
对象
DataTransfer
对象用于保存拖动并放下(drag and drop)过程中的数据。它可以报存一项或者多项的数据和每个拖拽项的类型(MIME 类型)
-
DataTransfer
对象包含拖拽事件的状态(例如事件的拷贝或者移动)。并且可以向拖拽数据中添加或删除项目的方法 -
在
DragEvent
接口有一个构造函数和一个dataTransfer
(dataTransfer 属性就是一个 DataTransfer 对象)属性
方法
getData(format)
:接受指定类型的拖放。如果拖放行为没有操作任何数据,会返回一个空字符串- 数据类型:
text/plain
、text/uri-list
- 数据类型:
setData()
:设置拖放操作的 drag 数据到指定的数据和类型(一般设置 MIME 类型)- 如果给定类型的数据不存在,则将其添加到拖动数据存储的末尾,使得
types
列表中的最后一个项目将是新类型 - 如果数据已经存在,则会替换当前位置的数据
- 如果给定类型的数据不存在,则将其添加到拖动数据存储的末尾,使得
setDragImage(img, xOffset, yOffset)
:设置为自定义图像。通常在dragstart
中使用此方法- 图像通常是一个 <image> 元素,也可以是 <canvas> 或者其他图像元素
xOffset
指示相对于图片的横向偏移量;yOffset
指向相对于图片的纵向偏移量
clearData([format])
:删除给定类型的拖动操作的。如果该数据不存在,不会进行任何操作format
:如果不指定数据类型,为空字符串或者空白。则会删除所有数据类型
//使用dragover阻止浏览器的默认行为.
//不能使用drapstart.drop需要拖拽元素在目标元素内才能完全触发
container.addEventListener("dragover", function (e) {
e.preventDefault()
})
box.addEventListener("dragstart", function (e) {
e.dataTransfer.setData("text/plain", "www.google.com")
const img = new Image()
img.src = "https://zyjcould.ltd/erciyuan/diana.png"
e.dataTransfer.setDragImage(img, 0, 0)
})
container.addEventListener("drop", function (e) {
let ele = e.dataTransfer.getData("text/plain")
console.log(ele, "drop")
})
属性
-
dropEffect
:用于控制在拖放过程中给用户的反馈(视觉上的),他会影响过程中光标手势。并且始终设置成 effectAllowed 的可能值之一copy
:操作用于指示被拖动的数据将从当前位置复制到放置位置move
:操作用于指定被拖动的数据将被移动link
:操作用于指示将在源和放置位置之间创建某种形式的关系或连接none
:项目可能禁止拖放
-
effectAllowed
:指定拖放操作所允许的一个效果none
:此项表示不允许放下copy
:源项目的复制项可能会出现在新位置copyLink
:允许 copy 或者 link 操作copyMove
:允许 copy 或者 move 操作link
:可以在新地方建立与源的链接linkMove
:允许 link 或者 move 操作move
:一个项目可能被移动到新位置all
:允许所有的操作uninitialized
:效果没有设置时的默认值,则等同于 all
box.addEventListener("dragstart", function (e) { e.dataTransfer.effectAllowed = "move" }) container.addEventListener("dragover", function (e) { e.preventDefault() ev.dataTransfer.dropEffect = "move" }) container.addEventListener("drop", function (e) { e.target.appendChild(box) })
-
fills
:属性在拖动操作中表示文件列表.如果操作不包含文件,则此列表为空- 所有type属性(attribute)为file的<input>元素都有一个files属性(property),用来存储用户所选择的文件
<input id="fileItem" type="file">
-
types
:只读属性。返回一个我们在事件中设置的拖动数据格式(setData())。格式顺序与拖动操作中包含的数据顺序相同 -
items
:DataTransfer 的 items 属性只读,是拖动操作中DataTransferItem
的DataTransferItemList
。- 一个
DataTransferItemList
对象,包含了表示拖动操作中被拖动项的 DataTransferItem 对象,每一个拖动项对应一个列表项 - 该列表包含了操作中每一项目的对应项,如果操作没有项目,则列表为空
- 一个
每个
DataTransfer
都包含一个 items 属性,这个属性是 DataTransferItem 对象的 list(列表)。即(DataTransferItemList)
DataTransferItem
描述了一个拖拽项。在一个拖拽中,每一个drag event
都有一个 dataTransfer 属性,它包含存有拖拽属性的list
,每一项都是一个 DataTransferItem
属性
kind
:拖拽项的种类,string
或者是file
type
:拖拽想的类型。一般是 MIME 类型
-
由于 items 并不是一个数组,这里使用的是
Array.from()
转换- 阻止了浏览器默认直接大开图片,拖动图片或者其他类型文件。可以在控制台看到打印
container.addEventListener("drop", function (e) { e.preventDefault() Array.from(e.dataTransfer.items).forEach(item => { console.log(item) }) })
方法
getAsFile()
:DataTransferItem
是一个文件,那此方法将返回拖拽项数据的 File 对象。否则返回 nullgetAsString(callback)
:当kind
属性是一个普通 Unicode 字符串时,该方法会用DataTransferItem
对象的 kind 属性作为实参来执行传入的回调函数- 该回调函数有权访问
DataTransferItem
的字符串数据
- 该回调函数有权访问
container.addEventListener("drop", function (e) {
e.preventDefault()
Array.from(e.dataTransfer.items).forEach(item => {
if (item.kind === "file") {
const file = item.getAsFile()
const url = URL.createObjectURL(file)
const img = new Image()
img.src = url
e.target.appendChild(img)
}
})
})
- 拖拽实现图片的上传功能
DataTransferItemList
对象是DataTransferItem
对象的列表.该属性可以向列表中添加拖拽项,从列表中移除拖拽项和清空列表中所有的拖拽项
DataTransferItemList
对象就是每个DragEvent
属性都有的dataTransfer
属性中的items
属性
属性
length
:李彪拖动项的数量
方法
add()
指定数据创建新的DataTransferItem
,并将其添加到拖动的DataTransferItemList
中add(data, type)
type 是MIME类型。例如text/html
或者text/plain
add(file)
文件对象,不需要给出任何类型- 如果该项目成功添加到 DataTransferItemList 中,则返回一个新创建的
DataTransferItem
对象.如果关键的 DataTransfer 对象没有数据存储,则返回 null
remove(index)
:方法从列表中指定删除指定索引处的DataTransferItem
。如果越界,则不会更改列表clear()
:将DataTransferItemList
中的所有DataTransferItem
删除
DataTransfer
和DataTransferItem
接口的一个主要的不同是前者使用同步的getData()
方法去得到拖拽项的数据,而后者使用异步的getAsString()
方法得到拖拽项的数据- 使用
e.preventDefault()
这个属性可以取消一些不必要的浏览器的默认事件
使用
mousedown
、mousemove
、mouseup
配合绝对定位absolute
来进行拖拽
mousedown
:这个阶段首先确定的就是鼠标相对于盒子内部的距离ol = pageX-offsetLeft
- 不光是
pageX
,也可以使用clientX
,在合适的情况下选择合适的属性
- 不光是
mousemove
:在执行阶段,目标是算出偏移量的距离,使用pageX-ol
。- ol就是鼠标距离拖拽目标的距离(是固定的)
mouseup
:在抬起阶段,解绑 mousemove 事事件。
<style type="text/css">
#box1 {
position: absolute;
width: 100px;
height: 100px;
background-color: red;
cursor: pointer;
}
</style>
<body>
<div id="box1"></div>
</body>
<script>
box1.addEventListener("mousedown", (e) => {
e.preventDefault();
bl = e.pageX - box1.offsetLeft
br = e.pageY - box1.offsetTop
function move(e) {
box1.style.left = e.pageX - bl + "px"
box1.style.top = e.pageY - br + "px"
}
document.addEventListener("mousemove", move, false)
document.addEventListener("mouseup", () => {
document.removeEventListener("mousemove", move)
})
})
</script>