javascript拖拽功能

717 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情

介绍

在JavaScript里实现拖拽功能可以使用draggable属性,draggable属性在大多数目前的浏览器中都可以兼容,是一个十分好用的属性。取值为一个布尔值,当取值为true的时候,可以用鼠标按钮拖动元素。拖拽操作期间,会有一个可拖拽元素的半透明快照跟随着鼠标指针

draggable

要使元素拖动的第一步是在元素本身加上draggable属性,这个属性是h5新增的,定义了这个属性之后就可以注册事件了,拖动的事件有好几个可以选择,拖动的时候分为开始、进行中、结束,拖动后放入相应区域又分为进入时、进入后、离开、放置

拖动时:

  • 开始 dragstart
  • 进行中 drag
  • 结束 dragend

进入区域

  • 进入时 dragenter
  • 进入后 dragover
  • 离开 dragleave
  • 放置 drop

我们使用一个案例来讲解这个draggable属性,编写了一段html代码,给要拖拽的图片加上draggable属性,左边是掘金的解码系列圆领卫衣,衣服领口有一个空的区域,右边是三个头像,我们要使用拖拽功能实现将头像拖动到空的区域,给卫衣找个主人

<div class="content">
    <section class="body">
        <div class="empty" id="empty"></div>
        <img class="clothes" src="./img/yifu.jpg" alt="">
    </section>
    <section class="head">
        <img draggable="true" src="./img/1.png" alt="one">
        <img draggable="true" src="./img/2.png" alt="two">
        <img draggable="true" src="./img/3.png" alt="three">
    </section>
</div>

image.png

class设置了empty的就是空的区域,我们先获取这个元素

const empty = document.querySelector('.empty');

里面有三张图片需要用循环来添加事件,为了简便直接给文档添加事件,在拖动图片的时候给拖动的图片加上边框,表示正在拖动哪张图片,这就需要用到拖动时的开始事件dragstart

document.addEventListener('dragstart',(e)=>{//拖动开始添加边框
  e.target.style.border='2px solid #ff0000'
},false)

69e68feb-9d1d-44da-9fae-4c409ee116aa.gif

可以看到拖动哪张图片哪张图片就会出现边框了,不过当拖动结束后这个边框依然存在,一般不拖动的时候会取消掉这个边框,这时候就用到拖动时的结束事件dragend去掉边框

document.addEventListener('dragend',(e)=>{//拖动结束去除边框
  e.target.style.border='none'
},false)

98ed3aef-5934-4381-bb78-ab1d6bf6aa77.gif

拖动结束时候边框消失了,但是当拖动图片进入空区域的的时候也要给空区域加一个边框来提示将图片拖动到正确的位置上,这里使用进入区域的dragenter

empty.addEventListener('dragenter',(e)=>{//进入时添加边框
  empty.style.border='2px solid #ff0000'
},false)

7ef95504-171a-4f21-9d46-c3d6833c507f.gif

可以发现dragstartdragenter函数里面都在重复同一件事情,这样的代码可以改善一下,只需要在拖动时使用drag事件添加边框就好了,在结束的时候再将边框去除掉就可以了,这样一来就实现了同步的效果

document.addEventListener('drag',(e)=>{
  e.target.style.border='2px solid #ff0000'
  empty.style.border='2px solid #ff0000'
},false)
document.addEventListener('dragend',(e)=>{
  e.target.style.border='none'
  empty.style.border='none'
},false)

每张图片都设置了alt属性,我们在拖拽开始的时候使用一个变量获取alt属性,在放置图片的时候依靠这个变量将拖动的图片使用appendChild添加节点到空区域

let name;
document.addEventListener('dragstart',(e)=>{
  name=e.target.alt
},false)

empty.addEventListener('dragover',e=>{
  e.preventDefault()//取消事件的默认动作,该方法将通知 Web 浏览器不要执行与事件关联的默认动作
},false)

empty.addEventListener('drop',(e)=>{
  e.preventDefault();
  e.target.appendChild(document.querySelector(`img[alt=${name}]`))
},false)

拖拽过程中发现并没有效果,空白区域也没有图片,那是因为浏览器默认不能在拖拽以后进行放置,因此我们需要在进入后和放置时使用preventDefault方法取消这个默认行为,这样就可以为空白区域添加图片了,

empty.addEventListener('dragover',e=>{
  e.preventDefault()
},false)
empty.addEventListener('drop',(e)=>{
  e.preventDefault();
  e.target.appendChild(document.querySelector(`img[alt=${name}]`))
},false)

但是拖动图片放置的时候只显示第一张放置的图片,我们得在进入时添加一个判断,空区域有节点了就去除掉,去除掉之后就可以实现效果了

document.addEventListener('dragenter',(e)=>{
  if(empty.firstChild){
    empty.removeChild(empty.firstChild)
  }
})

8b582c38-e8c3-48b5-b363-aa06a7e1b1a7.gif

理解并掌握draggable属性之后可以做一些自定义的动作,比如拖动排序,弹出框拖动移动等等

熊猫头真的挺配这件衣服的😂😂😂