当前位置: 首页 > Web前端 > HTML5

实现一个draggable-polyfill

时间:2023-04-05 21:43:19 HTML5

来美化原来的拖放。在HTML5普及之前,实现元素的拖拽还是比较麻烦的。总体思路是监控鼠标移动相关事件。以下为伪代码oDiv.onmousedown=function(ev){//记录起始位置}document.onmousemove=function(ev){//移动目标元素}document.onmouseup=function(ev){//取消鼠标移动event}HTML5new新增拖拽可拖动标准,拖拽变得简单。只需要监听元素的拖拽事件就可以实现各种拖拽功能。dragme

除了设置draggable="true"属性外,img和links默认都是可拖动的。当然,设置draggable="true"只是"dragable""拖动",松手后会恢复。如果需要拖动到指定位置,只需要在drop中记录即可dropbox.addEventListener('drop',function(ev){dragbox.style.left=XX;dragbox.style.top=XX;})原生拖拽原生拖拽有很多优点,大家可以自己去体会,就像原生和模拟器的区别一样。不过有点审美追求的肯定不会用原生默认的拖拽,因为真的不太好看。我们来看看原生的拖动效果。本机拖动效果是半透明预览(我们暂时称它为“幽灵”)。如果拖动的元素尺寸较小,生成的预览图可以接受,但只是半透明的。如果再大一点,那是不能接受的。“幽灵”不仅是半透明的,还有从鼠标位置向外扩散的渐变效果(真不知道是怎么设计的,可能是出于性能考虑),反正就是丑,如下。其次,还有一个效果就是被拖动的元素保持不动,但是被拖动的“鬼魂”在动。如果背景再复杂一点,那我就完全分不清了。比如下面的拖拽排序功能(仔细看上面那个“鬼”)是有的,但实在是说不清楚,谈不上自定义原生拖拽的体验。基本上,它不能定制。唯一可以更改的是setDragImage方法。您可以指定预览图像而不是默认预览图像。不过,这种方法也很鸡肋。自定义预览图还是和默认效果一样。它们都是半透明的。其次,实时生成当前节点的预览也比较麻烦。另一种思路其实更简单,如下。去除默认预览图并复制一份当前目标元素,cloneObj监听拖动事件,拖动后改变cloneObj的位置,去除cloneObj以下为伪代码,完整代码可查看文末1.去掉默认预览图虽然setDragImage比较鸡肋,但是我们可以设置透明图片来达到去掉默认预览图的效果dragbox.addEventListener('dragstart',function(ev){varimg=newImage();img.src="data:image/svg+xml,%3Csvgxmlns='http://www.w3.org/2000/svg'%3E%3Cpath/%3E%3C/svg%3E";ev.dataTransfer.setDragImage(img,0,0);}普通元素设置draggable="true"后,Chrome可以直接拖拽,FireFox需要设置ev.dataTransfer.setData('text','anyvalue')在dragstart.2.复制当前目标元素,cloneObj复制当前目标元素,并设置position:fixed等属性,可以悬浮在页面上,然后添加到body中,如下varcloneObj=this.克隆节点(真);cloneObj.style='位置:固定;left:0;top:0;z-index:999;pointer-events:none;transform:translate3d('+left+'px,'+top+'px,0);'document.body.appendChild(cloneObj);3.监听拖动事件,拖动元素时改变cloneObj的位置并触发拖动事件,类似于鼠标移动事件,可以获取当前鼠标位置(拖动过程中不触发mousemove事件),以及也可以隐藏Originaltargetdragbox.addEventListener('drag',function(ev){if(cloneObj){cloneObj.style.transform='translate3d('+left+'px,'+top+'px,0)';dragbox.style.visibility='可见';}})Chrome确实是这样,虽然FireFox也可以触发drag事件,然后无法获取到鼠标位置信息(全0),所以我们只能把listener放在dragover上,虽然不完美,但是也是一种方法document.addEventListener('dragover',function(ev){if(cloneObj){cloneObj.style.transform='translate3d('+left+'px,'+top+'px,0)';}})4.拖拽后移除cloneObj,恢复原来的targetdraggable-polyfill根据上面的思路,一个draggable-polyfill就完成了,这个polyfill的功能很简单,只是美化了原来的拖拽,去掉了原来的半透明预览图,没有改变原来的逻辑,如只要项目中使用了原来的拖放,就可以应用这个补丁比如上面的拖拽排序,引用这个polyfill后,效果如下项目地址https://github.com/XboxYan/draggable-polyfill使用起来也很简单,直接引用即可如果是工程项目,也可以使用npm安装npmidraggable-polyfill然后直接导入。导入可拖动填充;有关更多示例,请参见http://xboxyan.codelabo关于.cn/draggable-polyfill/example/index.html需要注意的一点是,因为仅复制当前节点,如果您的样式依赖于父节点,则复制的样式将不同于原来的target.parent。dragbox{background:red}/*改成*/.dragbox{background:red}其他的技巧,大家可以在网上找一个原生拖动的案例,把上面的draggable-polyfill.js直接粘贴到控制台,就可以了可以马上“试一试”,比如本例中,打开控制台进行粘贴,回车即可看到拖动效果(如下)。