写点什么

html5 鼠标拖动排序及 resize 实现方案分析及实践

用户头像
zhoulujun
关注
发布于: 2021 年 07 月 14 日

对列表进行拖动排序,尺寸改变。之前一般会使用 jQuery-UI。其通过 mousedown、mousemove、mouseup 这三个事件来实现页面元素被鼠标拖拽的效果。vue-drag-resize vuedraggable 等包也大抵如此:https://codepen.io/lujun-zhou/pen/LYybXNx


而 HTML5 中直接提供了拖放的 API,只要通过监听元素的拖放事件就能实现各种拖放功能。


拖放(Drag 和 drop)是 HTML5 标准的组成部分。相比之前用 jquery-UI 等库实现,更加方便(省去计坐标计算等)。


为了使元素可拖动,必须把 draggable 属性设置为 true :


<div id=test draggable=true>test</div>[object Object]整个拖拽事件触发的顺序如下:dragstart-> drag -> dragenter -> dragover -> dragleave -> drop ->dragend


拖放事件事件详情一个元素被拖放,他可能会经过很多个元素上,最终到达想要放置的元素内。这里,我暂时把被拖放的元素称为源对象,被经过的元素称为过程对象,到达的元素称为目标对象。不同的对象产生不同的拖放事件。


源对象事件:dragstart:源对象开始拖放,开始移动时事件触发


drag:源对象拖放过程中,移动被拖拽对象时触发
dragend:源对象拖放结束,整个拖放操作结束时触发。
复制代码


过程对象事件:dragenter:源对象进入过程对象范围内,被拖拽对象进入过程对象时被触发


dragover:源对象在过程对象范围内移动,被拖拽对象在过程对象内移动时触发
dragleave:源对象离开过程对象的范围,被拖拽对象离开目标对象时触发
复制代码


目标对象事件:drop:源对象拖放到目标对象中,目标对象完全接受被拖拽对象时触发,可理解为在目标对象内松手时触发。


dragenter 和 dragover 事件的默认行为是拒绝接受任何被拖放的元素。因此,我们必须阻止浏览器这种默认行为。e.preventDefault();


如果 drop 接收盒子要想接收到元素,那么接收的拖动元素 dragenter 和 dragover 必须阻止默认行为。


el.ondragover = function(e){e.preventDefault();}el.ondrop = function(e){e.preventDefault();}在 vue 项目中:


@dragstart.native="dragStart(index,event)"@dragleave.native.prevent@dragover.native.prevent@dragend.native="dragend(index,event)"这样才会触发 drop


dataTransfer 对象在所有的拖放事件中都提供了一个数据传输对象 dataTransfer,主要是用于在源对象和目标对象之间传递数据。


dataTransfer 方法 setData(format, data)设置拖拽事件中要传递的数据,format 的参数为数据类型,data 要存入的数据。例如:event.dataTransfer.setData('text/plain', 'hello world')


存入的数据类型,共有 4 种:


text/plain


text/html


text/xml


text/uri-list


注:如果给定类型的数据不存在,则将其添加到拖动数据存储的末尾,使得 dataTransfer.types 列表中的最后一个项目将是新类型。


getData(format)该方法从 dataTransfer 对象中读取数据,参数为在 setData 方法中指定的数据类型,例如:event.dataTransfer.getData('text/plain')


clearData()该方法清空 dataTransfer 对象中存储的数据,参数可选,为数据类型。若为空,则清空所有数据。


setDragImage(element,x,y)该方法通过 img 元素来设置拖放图标


element 表示拖拽时鼠标下面的图片(通常是 image 元素,也可以说 canvas 元素)


x、y 分别指示相对于图片的横向和纵向偏移量,相对应鼠标指针。


dataTransfer 属性 dropEffect 和 effectAllowed 属性给指定拖放操作所允许的一个效果,例如:dataTransfer.effectAllowed = "move"。


effectAllowed 用来指定当元素被拖放式所允许的视觉效果。如果 effectAllowed 属性是定为 none,则不允许拖放元素


dropEffect 表示拖放操作的视觉效果,如果 dropEffect 属性设定为 none,则不允许被拖放到目标元素中。


应该在 dragstart 事件中设置此属性,以便为拖动源设置所需的拖动效果。在 dragenter 和 dragover 事件处理程序中,该属性将设置为在 dragstart 事件期间分配的任何值,因此,可以使用 effectAllowed 来确定允许哪个效果。其值如下(dropEffect 只有 none 、copy、move、link):


none 、copy、move、link,copyMove,linkMove、all、uninitialized


chrome 默认是显示一个绿色的加号,设置:$event.dataTransfer.effectAllowed = 'move'。则恢复成默认鼠标样式。


files 属性返回被拖拽的文件列表,是一个 FileList 对象,有 length 属性,可通过下标访问。此功能可用于将文件从用户桌面拖动到浏览器。一般配合 FileReader 来处理文件。如 FileReader.readAsDataURL 与 FileReader.onload


拖动元素排序实现之前写了两篇文章,有读者留言希望看代码,这次大致写了下


https://codepen.io/lujun-zhou/pen/KKmNgxv


vue 实现


https://codepen.io/lujun-zhou/pen/zYwozMZ


magicBox tab 排序也是,就是采用这个方案。


1626167489953.jpg


画布元素位置与尺寸调整可以先回顾下《再谈 BOM 和 DOM(6):dom 对象及 event 对象位值计算—如 offsetX/Top,clentX》


如果使用 mouse 事件控制,就显得非常复杂。这种一般都是使用第三方库实现,如 interact.js 、vue-drag-resize 等。


如果直接使用 css resize,然后通过 resizeObserve 回调尺寸改变,实现起来就变得简单的多。


这种思路之前也介绍过,如《懒加载优化:JavaScript IntersectionObserver API 监听元素是否可见》。


这里的大致实现代码:


https://codepen.io/lujun-zhou/pen/jOmVLGy


之前做过一版类似 DataV 的需求,就是直接用 html5 原生属性写的。


canvas 画布实现:https://codepen.io/atindo23/pen/OJLbdrJ


鼠标缩放元素操作


缩放事件,实现不肖多说,MDN 案列写的够好了


https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onwheel


参考文章:


HTML5--拖放事件与 dataTransfer 对象 https://blog.csdn.net/hjc256/article/details/89021483


说说 HTML 中的 dropEffect 和 effectAllowed https://blog.csdn.net/gggg5643/article/details/52135824


HTML5 进阶系列:拖放 API 实现拖放排序 - 林鑫的文章 - 知乎 https://zhuanlan.zhihu.com/p/26666141


HTML5 前端技术教程:H5 拖放 - 方伟景的文章 - 知乎 https://zhuanlan.zhihu.com/p/47458212


转载本站文章《html5 鼠标拖动排序及 resize 实现方案分析及实践》,请注明出处:https://www.zhoulujun.cn/html/webfront/SGML/html5/2016_0124_434.html

用户头像

zhoulujun

关注

还未添加个人签名 2021.06.25 加入

还未添加个人简介

评论

发布
暂无评论
html5鼠标拖动排序及resize实现方案分析及实践