1.首先,为了使元素可拖动,要先设置元素为可拖拽
- 方法:添加draggable属性,设置为 true
- 注意:链接和图像默认就支持拖拽,另外,如果一个元素中的文本被选中,那么这个元素和他的文本节点此时都支持被拖拽。
<body style="padding:30px;">
<div class="item">
<h3 draggable="true">我是被允许拖拽的h3元素</h3>
</div>
<div class="item">
<a href="http://www.baidu.com/">a链接</a>
</div>
<div class="item">
<img src="timg.jpg" alt="" width="200">
</div>
<div class="item">
<h3>选中文字后可被拖拽</h3>
</div>
</body>
<script>
document.ondragstart = function(){
console.log('dragstart')
}
</script>
2.拖拽事件监听
- 拖拽事件一律使用(推荐)document监听,拖拽事件分2种,一种针对的是被拖拽的元素,第二种针对被拖拽的元素经过的容器
事件名称 |
事件对象(e.target) |
说明 |
ondrag |
被拖拽的元素 |
元素被拖拽期间(持续)触发 |
ondragstart |
被拖拽的元素 |
开始拖拽元素时触发(推荐使用它记录被拖拽的元素) |
ondragend |
被拖拽的元素 |
元素拖拽结束时触发 |
ondragenter |
接收容器 |
被拖拽的元素进入当前容器范围内时触发此事件 |
ondragover |
接收容器 |
被拖拽的元素停留在当前容器范围内(持续)触发此事件 |
ondragleave |
接收容器 |
被拖拽的元素离开当前容器范围内时触发此事件 |
ondrop |
接收容器 |
释放鼠标键时触发此事件(触发时间早于ondragend) |
- 注意:浏览器默认阻止ondrop事件,需要在ondragover事件中阻止默认事件它才能被触发
3.完整的拖拽实例
- 哪个元素被拖拽:可以在ondragstart事件中获取被拖拽的元素,并保存,问题1解决
- 哪个容器负责接收:实际操作中,拖拽结束时经过的容器就是接收的容器,而能在此时获得接收容器的事件只能是drop事件(而drop事件默认被屏蔽,所以需要在ondragover事件中释放此事件)
<script>
// 设置全局变量记录被拖拽的元素
var dragNode = null
// 监听拖拽开始,记录被拖拽的元素
document.ondragstart = function (e) {
//记录被拖拽的元素
dragNode = e.target
// 修改通明度
dragNode.style.opacity = 0.5
}
// 监听拖拽结束
document.ondragend = function (e) {
// 恢复透明度
e.target.style.opacity = 1
// 清空dragNode
dragNode = null
}
// 阻止默认事件
document.ondragover = function (e) {
//允许被拖拉的节点放入目标节点
e.preventDefault()
}
// 监听拖拽释放,获取当前容器
document.ondrop = function (e) {
// 获取释放时的容器
var targetBox = e.target
// 判断是否是目标容器
if(targetBox.matches(".box")){
// 将元素移动到新的容器中
targetBox.appendChild(dragNode)
}
}
</script>
4.优化
- 存在的问题:前面的案例中我们使用了一个全局变量来存储被拖拽的元素,但是使用全局变量容器污染全局
- 解决办法:在拖拽事件中,事件对象event有一个dataTransfer属性对象,用来保存和读取拖放相关的数据
方法 |
说明 |
e.dataTransfer.setData(key,data) |
设置数据(只能传入数字或者字符串) |
e.dataTransfer.getData(key) |
取数据(数字或者字符串) |
e.dataTransfer.clearData(key) |
清空数据 |
- 代码实现:使用e.dataTransfer记录被拖拽元素的id属性值,从而通过这个值获取获取到被拖拽的元素
<script>
// 监听拖拽开始,记录被拖拽的元素
document.ondragstart = function (e) {
//判断节点是元素节点且有id属性,没有则赋予一个id
if(!e.target.id && e.target.nodeType === 1){
// 如果没有id,则设置一个id
e.target.id = "dragTest"
}
//保存id信息
e.dataTransfer.setData("id",e.target.id)
// 修改通明度
e.target.style.opacity = 0.5
}
// 监听拖拽结束
document.ondragend = function (e) {
// 恢复透明度
e.target.style.opacity = 1
}
// 阻止默认事件
document.ondragover = function (e) {
//允许被拖拉的节点放入目标节点
e.preventDefault()
}
// 监听拖拽释放,获取当前容器
document.ondrop = function (e) {
// 获取释放时的容器
var targetBox = e.target
// 根据存储的数据获取被拖拽的元素
var id = e.dataTransfer.getData("id")
var dragNode = document.querySelector("#"+id)
// 判断是否是目标容器
if(targetBox.matches(".box")){
// 将元素移动到新的容器中
targetBox.appendChild(dragNode)
}
}
</script>