最近在一个vuejs的前端项目中,需要实现一个通过鼠标点击并拖拽,让页面中的图片框位置发生移动的功能。该图片框是浮在其父div元素之上的,并不参与到其父div的文档结构中。由于功能比较简单,因此没有去用一些复杂的方法或者组件来实现该功能。而且虽然是vue的项目,但是这个功能更应该使用原生的ondrag方式去实现。
如果要实现图片框在其父div的内部简单地拖拽移动,那么前提是该可拖拽图片框的父元素必须设置为position:relative
,然后将图片框的position设置为position:absolute
,并且图片框的z-index要设置得高于父div,以免被其他元素给遮挡住了。为了不让图片框内部的元素触发拖拽时间,成为事件的target,我们应该在图片框添加pointer-events: none
,这样一来只有图片框最外层包裹元素可以触发拖拽的事件了;在vue中可以在事件监听处使用.self
语法糖来阻止该事件向下传播。
比较重要的一点是,我们需要在图片框最外层包裹元素上加上draggable="true"
属性,表明他是一个可以被拖拽的元素。为了实现元素的拖拽移动效果,我们使用到了原生的ondragstart和ondragend事件,下面简单展示一下这两个事件触发时需要执行的逻辑代码。
1 | dragStart(ev) { |
拖拽事件开始时,我们只需要记录开始拖拽时鼠标位置距离屏幕坐标系的坐标,也就是clientX和clientY。我们通过在event中获取到这些值,其实所有的值都是通过在event中获取到的,这里我们代码中将event写成了ev。
1 | dragEnd(ev) { |
在拖拽结束时,我们记录结束时鼠标位置距离屏幕坐标系的坐标,也就是clientX和clientY。将结束坐标和开始坐标做减法,就可以得到拖拽后的元素在x轴和y轴的偏移量。那么简单来说,此时用元素之前相对于父元素的位置ev.target.offsetTop
和ev.target.offsetLeft
分别加上两个坐标轴的偏移量,并赋值给ev.target.style.top
和ev.target.style.left
,就能将元素移动到拖拽结束时的位置了,也就实现了元素拖拽移动效果。
不过我们需要实现图片框只能在父div内部拖动,不能让图片框最终位置超出父div,因此在dragend方法中,还需要根据实际情况获取到其父div的宽高值,并带到if条件中进行判断,就可以保证图片框无法超出父div的上下左右了,原理就是如果图片框超出了父元素,那么就通过设置位置,让元素在超出的那个水平或者垂直位置贴边即可。
比较容易迷惑人的点在于,如果父div设置了relative,而图片框设置了absolute,那么图片框的offsetTop和offsetLeft都是相对于父div的,这个属于是html的基础知识,不过很多时候用得少,所以容易弄错。
*该文章原创并发表于吱托邦网站,未经允许禁止转载!