让拖拽更人性化——如何自定义拖拽风格?
时间:2023-03-19 17:26:49
科技观察
Web开发中,经常会遇到需要拖拽的场景。为了更好的体验,拖动区域需要有一定的变化提示,告诉用户:“现在可以放到这里了~”,比如这样。dragover效果这一次,让我们探讨一下如何自定义dragover样式。1、dragenter和dragleave要达到这样的效果,处理dragenter和dragleave是少不了的。当拖动的元素进入有效的放置目标时,将触发dragenter事件。当拖动的元素离开有效的放置目标时,将触发dragleave事件。拖放目标假设有这样一个结构,其中img是拖放目标,div.content是放放目标。![]()
然后听文档;document.addEventListener('dragleave',function(ev){console.log('dragleave',ev.target)})文档。addEventListener('draenter',function(ev){console.log('draenter',ev.target)})那么在将img拖入div.content的过程中,肯定会触发dragenter和dragleave事件,如如下:dragenter和dragleave如果页面比较简单,自定义拖动过程更容易;document.addEventListener('dragleave',function(ev){ev.target.toggleAttribute('over',false);})文档。addEventListener('dragenter',function(ev){ev.target.toggleAttribute('over',true);})通过添加over属性自定义样式;.content[over]{outline:4pxsolidslateblue;}效果如下:dragover效果是不是很简单?实际使用中还有很多局限性,下面会一一介绍。2.当放置目标有子元素时,大多数情况下,放置目标不为空,还有其他子元素。如果使用上面的方法,就会出现问题。假设布局是这样的,为了区分,可以给需要放置的元素加上一个属性,比如allowdrop,表示允许放置;
![]()
不允许放置
这里通过属性区分:document.addEventListener('dragleave',function(ev){if(ev.target.getAttribute('allowdrop')!==null){ev.target.toggleAttribute('over',false);}})document.addEventListener('dragenter',function(ev){if(ev.target.getAttribute('allowdrop')!==null){ev.target.toggleAttribute('over',true);}})效果如下:当有子元素时看到,拖动目标经过子元素时元素,外部样式已经丢失。原因其实很简单。在穿过子元素时,droptarget也会触发dragleave事件!有没有办法不触发它?这里有两种方式:一是可以取消对dragleave的监听,因为在执行dragleave时,元素本身并不知道即将进入哪个区域,很容易“误伤”。而是每次dragenter,先去掉上一个droptarget的属性,再添加一个新的,有点类似tab的操作。具体实现如下:varlastDrop=null;document.addEventListener('draenter',function(ev){if(lastDrop){lastDrop.toggleAttribute('over',false);}constdropbox=ev.target.closest('[allowdrop]');//获取最近的放置目标if(dropbox){dropbox.toggleAttribute('over',true);lastDrop=dropbox;}})还有另一种方法:使用CSS非常简单。这里有一个非常简单粗暴的方法直接禁止子元素的鼠标响应,如下:.content[allowdrop](empty::after{"allowdrop")*{pointer-events:none;}没有元素响应了,完美。在子元素的情况下,上面完美的三、多层嵌套放置目标的方法其实可以解决大部分问题,毕竟大部分场景都是平面的。但是,有时候会遇到多层结构,比如可视化编辑工具,尤其是现在流行的低代码平台,会涉及到多层结构,假设HTML就是这样。
![]()