当前位置: 首页 > 科技观察

教你自定义拖拽样式,md

时间:2023-03-21 17:14:24 科技观察

web中图片默认可以拖拽,一般是半透明预览图(以下简称“预览图”),如下:这个预览图是自动拖拽的是系统生成的,一般是不能自定义的,但是有时候你会觉得拖出来的预览图尺寸太大,不方便放置,比如这个场景。这是一个拖拽图片保存的功能。您需要将图片拖放到指定区域,才能触发保存操作。因为拖动时预览图太大,覆盖了放置区域,体验很差。如果预览图片的尺寸可以小一些,比如这样:体验会不会好很多?下面一起来探讨一下。1.预览图的默认尺寸首先,拖动预览图的尺寸与页面上图片的CSS尺寸有关,也就是说显示的图片越大,拖动预览图越大。但是,预览图像的大小不是无限的。根据我的测试,预览图的最大尺寸是400*400,比如下图尺寸是500*500,但是拖动出来的预览图只有400*400,但是在实际开发中,这个尺寸还是太大了。以上是MacOSChrome下的性能效果,Firefox性能要好很多,预览图也不会太大。另外我测试了WindowsChrome的性能,类似,只是最大尺寸为200*200,性能如下:2.借助setDragImage修改预览图原生拖拽只能修改预览图通过setDragImage[1],看到好像很强大,其实很鸡肋。简单使用如下:functiondragstart_handler(ev){varimg=newImage();img.src='例子.jpg';ev.dataTransfer.setDragImage(img,0,0);}这里指定这样一张图片为预览图:需要绑定dragstart事件,这里采用事件委托的方式。document.addEventListener('dragstart',ev=>{if(ev.target.tagName==='IMG'){dragstart_handler(ev)}})效果是这样的:为什么第二次拖动出现custom呢预览?这是肋骨所在的位置。官方规则是example.jpg是现有图像。如果尚未创建或加载此图像,浏览器将使用默认的拖动图像。第二次拖动后拖动时,加载了图片,所以生效了。可以说,几乎所有setDragImage不起作用的情况都是出于这个原因。另外还有一个问题就是不能直接指定预览图的大小,例如:functiondragstart_handler(ev){varimg=newImage();img.src='例子.jpg';img.width=50;//无效的img.height=50;ev.dataTransfer.setDragImage(img,0,0);}这也是无效的,内存中的图片会以原来的大小显示。3.将预览图指定为页面元素其实如果要修改预览图的大小,可以通过canvas渲染原图,然后修改大小生成图片,但是canvas往往有交叉渲染图片时的domain问题,canvas也有一定的门槛,这里就不使用了。回头看看官方的语法:dataTransfer.setDragImage(img|element,xOffset,yOffset);可以看到,第一个参数不仅支持动态创建的图片,还支持页面上实际存在的元素(页面上存在的元素必须加载)。假设我们在页面中添加一个自定义预览图像。然后指定预览为图片example.jpg。ev.dataTransfer.setDragImage(img,0,0);效果如下:可以看到,拖动图片就像拖动example.jpg一样,也可以直接通过CSS修改大小!#img{宽度:100px;height:100px;}预览图的大小也遵循example.jpg。如果把example.jpg替换成和原图一样的链接,是不是相当于自定义了预览图的大小?现在您需要隐藏自定义图像。毕竟只是借用而已,不需要展示在页面上。这里需要一个小技巧,你不能真正隐藏这个图像,例如:#img{display:none;/*或*/不透明度:0;/*or*/visibility:none}这些方法都不行,因为预览图是跟着这个自定义图片的,如果直接隐藏,预览图会直接消失。此时采用的方法可以将这张图片移出视口,例如:#img{position:absolute;top:-9999px;}这样就没有问题了。实际工作中应该自动生成这张图片,自动获取当前拖拽图片的链接,完整的实现就是这样。/**custom_drag_img*author:xboxyan*/constimg=document.createElement('img');img.style="position:absolute;top:-9999px;max-width:100px;max-height:100px;"文档.body.append(img)document.addEventListener('dragstart',ev=>{if(ev.target.tagName==='IMG'){img.src=ev.target.src;ev.dataTransfer.setDragImage(img,0,0);}})可以把这段代码注入其他地方试试效果。比如原效果是这样的:注入上面代码后的效果是这样的:是不是某些场景下体验好很多?4.自定义预览图样式上面的预览图不仅可以指定图片元素,还可以给其他元素添加一些装饰,比如div。

.drag_img{位置:绝对;顶部:-9999px;最大宽度:100px;最大高度:100px;边框:3px纯黄色;}这样就可以给预览图加上黄色边框(强调)。或者通过伪元素添加角标。.drag_img::after{内容:'';位置:绝对;顶部:0;右:0;宽度:20px;高度:20px;背景:线性渐变(-135deg,#f4433650%,透明51%);}但是添加cssfilter不生效,还是原来的样式:.drag_img{position:absolute;顶部:-9999px;最大宽度:100px;最大高度:100px;过滤器:棕褐色(1);/*brownfilter*/}这可能与系统生成预览图的策略有关,未知,不可修改。它也只适用于图像拖动(但性能超级好)。如果要完全自定义拖动效果,自定义普通的可拖动元素,必须通过JS模拟实现。大致思路如下:去掉默认预览图,复制一份当前目标元素,cloneObj监听拖拽事件,通过transform改变cloneObj的位置。拖动后,移除cloneObj。详细原理可以参考我之前的文章:实现一个美化的原生拖拽draggable-polyfill[2],虽然是自定义实现,但是完全不影响原有的业务拖拽逻辑。这就是polyfill的魅力所在,非常适合原生拖拽实现的场景。项目地址:https://github.com/XboxYan/draggable-polyfill(或访问文章底部“原文链接”)[3],非常轻量,100行代码,不影响业务逻辑,非常适合学习,适时使用,欢迎star~3年前的老代码,最近优化了一波,很实用,欢迎star6。综上所述,图片拖拽预览自定义完成。其实主要是用来修改预览大小的。在某些场景下是相当有用的。这里有一些要点:拖动过程中生成的预览图是系统生成的,不能直接修改。在macOSChrome下,预览图最大尺寸为400*400。在某些场景下体验不是很友好。setDragImage可以修改预览图。setDragImage需要加载图片才能生效,否则还是默认样式。setDragImage可以指定页面上的其他元素,不仅imgsetDragImage指定的元素不能真正隐藏,否则预览图不可见,可以将它移到看不见的地方。以上方案适用于图片拖动,自定义样式受限。如果需要完全自定义拖动,可以使用draggable-polyfill方案。欢迎star~总的来说,整体实现还是很简单的。既然是原生方案,性能就不用多说了,也不影响原有的功能。起到美化作用。如果你有类似的需求,请速速使用~参考[1]setDragImage:https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage。[2]实现一个美化原生拖放的draggable-polyfill:https://segmentfault.com/a/1190000020842646。[3]https://github.com/XboxYan/draggable-polyfill:https://github.com/XboxYan/draggable-polyfill。