基本语法及事件
draggable 属性规定元素是否可拖动。必须设置,否则没有拖拽效果及事件触发
提示: 链接和图像默认是可拖动的。
提示: draggable 属性经常用于拖放操作
语法
<element draggable="true|false|auto">
值 | 描述 |
---|---|
true | 规定元素是可拖动的。 |
false | 规定元素是不可拖动的。 |
auto | 使用浏览器的默认特性。 |
在拖放过程中会触发以下事件:
在拖动目标上触发事件(源元素),作用于被拖拽元素上
- ondragstart - 开始拖动元素触发
- ondrag - 元素正在拖动时触发
- ondragend - 用户完成元素拖动后触发
<div id="app">
<div class="drag" draggable="true"></div>
<div class="target"></div>
</div>
<script>
const drag = document.querySelector('.drag')
const target = document.querySelector('.target')
drag.addEventListener('dragstart', ondragstart)
drag.addEventListener('drag', ondrag)
drag.addEventListener('dragend', ondragend)
function ondragstart(event) {
console.log('开始拖动')
}
function ondrag(event) {
console.log('正在拖动')
}
function ondragend(event) {
console.log('完成拖动')
}
</script>
作用于目标元素
- ondragenter - 进入其容器范围内触发(当被鼠标拖动的源元素进入目标容器范围内时触发)
- ondragover - 被拖动的源对象在目标容器中拖动时触发
- ondragleave - 拖动的对象离开目标容器时触发
- ondrop - 释放鼠标时触发
Event.preventDefault
阻止默认事件,在ondragover中一定要执行preventDefault方法,否则ondrop不会被触发
<div id="app">
<div class="drag" draggable="true"></div>
<div class="target"></div>
</div>
<script>
const drag = document.querySelector('.drag')
const target = document.querySelector('.target')
target.addEventListener('dragenter', ondragenter)
target.addEventListener('dragover', ondragover)
target.addEventListener('dragleave', ondragleave)
target.addEventListener('drop', ondrop)
function ondragenter(event) {
console.log('进入入其容器范围内触发')
}
function ondragover(event) {
event.preventDefault()
console.log('容器中拖动时触发')
}
function ondragleave(event) {
console.log('离开目标容器时触发')
}
function ondrop(event) {
console.log('释放鼠标时触发')
}
</script>
DataTransfer
在进行拖放操作的时候,dataTransfer对象可以用来保存被拖动的数据。它可以保存一项或多项数据、一种或多数数据类型。通谷一点讲,就是可以通过它来传输被拖动的数据,以便在拖拽结束的时候,对数据进行其他的操作。
- setData(type, data): 用于声明所发送的数据
- getData(type):用于获取指定type的数据 注意:只能在ondrop中获取的到
- clearData(type):用于清除指定类型的数据
<div id="app">
<div class="drag" draggable="true"></div>
<div class="target"></div>
</div>
<script>
const drag = document.querySelector('.drag')
const target = document.querySelector('.target')
drag.addEventListener('dragstart', dragstart)
target.addEventListener('dragover', ondragover)
target.addEventListener('drop', ondrop)
function dragstart(event) {
event.dataTransfer.setData('comp', JSON.stringify({name: 'WFT'}))
}
function ondragover(event) {
event.preventDefault()
}
function ondrop(event) {
let data = JSON.parse(event.dataTransfer.getData('comp'))
console.log(data)
// ...
// 处理完数据 最后清除一下
event.dataTransfer.clearData()
}
</script>
在其它的事件(如ondragover
、ondragleave
等),是无法获取dataTransfer里面的值了。这是由于W3C要求对dataTransfer里的值进行保护[参考]。因此,如果需要在这些事件里获取数据,只能通过一个全局变量等其它方式来实现了。
event.dataTransfer.setDragImage(p_w_picpath, x, y)
setDragImage方法用于在拖放操作过程中,修改鼠标指针所指向的图像
示例一:
先看效果:
先说一下,这种和鼠标去拖拽某个元素跟着鼠标移动一直移动不一样的,那种核心用到三个鼠标事件是 onmousedown、onmousemove、onmouseup。咱们这种是拖拽、就是本身是不动的状态
下面是完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div class="drag" draggable="true"></div>
<div class="target"></div>
</div>
<script>
const drag = document.querySelector('.drag')
const target = document.querySelector('.target')
drag.addEventListener('dragstart', dragstart)
target.addEventListener('dragover', ondragover)
target.addEventListener('drop', ondrop)
let curDragDom = null
let curOffsetX = 0
let curOffsetY = 0
// 开始拖拽
function dragstart(event) {
curDragDom = this
curOffsetX = event.offsetX
curOffsetY = event.offsetY
}
// 在目标元素中拖拽 移除掉默认事件 否则不会触发 drop事件
function ondragover(event) {
event.preventDefault()
}
// 在目标容器中松开鼠标
function ondrop(event) {
if(!curDragDom) return
let copyDom = curDragDom.cloneNode(true)
copyDom.style.position = 'absolute'
const { x, y } = this.getBoundingClientRect()
copyDom.style.left = event.clientX - x - curOffsetX + 'px'
copyDom.style.top = event.clientY - y - curOffsetY + 'px'
copyDom.removeAttribute('draggable')
this.appendChild(copyDom)
}
</script>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#app {
width: 100vw;
height: 100vh;
padding: 50px 0 0 50px;
box-sizing: border-box;
display: flex;
}
.drag {
width: 100px;
height: 100px;
background-color: red;
}
.target {
width: 400px;
height: 400px;
border: 1px solid red;
margin-left: 200px;
position: relative;
overflow: hidden;
}
</style>
</body>
</html>
示例二:
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div class="upload" draggable="true">
<div>将文件拖到此处进行上传</div>
</div>
<div class="images"></div>
</div>
<script>
const upload = document.querySelector('.upload')
const imageContainer = document.querySelector('.images')
upload.addEventListener('dragover', ondragover)
upload.addEventListener('drop', ondrop)
function ondragover(event) {
event.preventDefault()
}
function ondrop(event) {
event.preventDefault()
const { files } = event.dataTransfer
Array.from(files).forEach(blob => {
const url = window.URL.createObjectURL(new Blob([blob]))
const img = document.createElement('img')
img.src = url
imageContainer.appendChild(img)
})
}
</script>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#app {
width: 100vw;
height: 100vh;
padding: 50px 0 0 50px;
box-sizing: border-box;
}
.upload {
width: 360px;
height: 180px;
border: 1px dashed #c0c4cc;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
}
.upload > div {
color: #606266;
font-size: 14px;
}
.images {
width: 100%;
display: flex;
flex-wrap: wrap;
margin-top: 10px;
}
.images img {
width: 300px;
height: 180px;
margin-right: 20px;
}
</style>
</body>
</html>