让拖拽更加人性化-如何自定义 Dragover 样式?

网站建设3年前发布
33 0 0

在 web 开发中,经常会碰到需要拖拽的场景。为了更好的体验,拖拽区域需要有一定的变化提示,告诉用户:"现在可以放在这里了~",例如这样的。,dragover效果,这次接着探索一下如何自定义 dragover 样式。,要实现这样的效果,少不了和dragenter和dragleave打交道。,拖拽目标和放置目标,假设现在有这样一个结构,这里 img是拖拽目标,div.content是放置目标。,然后在document监听一下;,那么,将img拖入div.content的过程中,肯定会触发dragenter和dragleave这两个事件,如下:,dragenter和dragleave,如果页面比较简单,要自定义拖拽过程就比较容易了;,通过添加over属性自定义样式;,效果如下:,dragover效果,是不是非常容易呢?,实际使用起来其实还存在很多局限性,下面一一介绍。,大部分情况下,放置目标并不是空的,还有其他子元素,如果采用上面的方式就会有问题了,假设布局是这样的,为了区分,可以给需要放置的元素添加一个属性,比如allowdrop,表示允许放置;,这里通过属性区分一下:,效果如下:,有子元素的情况下,可以看到,当拖拽目标经过子元素时,外面的样式已经丢失了。原因其实很简单,在经过子元素时,放置目标也触发了dragleave事件!,那有没有办法不触发呢?这里有两种方式:,首先可以取消dragleave的监听,因为在执行dragleave时,元素本身是不知道即将进入哪一个区域,很容易“误伤”。取而代之的是每次dragenter时,先移除上一次放置目标的属性,然后再添加新的,有点类似选项卡的操作,具体实现如下:,还有另一种方式:借助 CSS 就非常容易了。,这里有一个非常简单粗暴的方式,直接将子元素禁用鼠标响应,如下:,这样,在滑过任何子元素都不会有响应了,完美。,有子元素的情况,完美,上面这种方式其实可以解决大多数问题了,毕竟大部分场景都是扁平的。不过有时候也会碰到多层结构,比如那种可视化编辑工具,尤其是目前比较火的低代码平台,就会涉及到多层结构,假设 HTML 是这样的。,如果按照 CSS 的处理方式(JS 方式没有问题),由于所有子元素都被禁用,里面的结构自然也无法响应了。,多层嵌套结构无响应,那如何让里面的放置目标可以响应呢?其实只需要改一下上面的 CSS 即可,如下:,这里使用了>选择器,表示只选择子元素,不包含后代元素,然后排除掉放置目标,这样就能实现多层嵌套了,效果如下:,多层嵌套结构,完美,是不是出乎意料的简单呢?,不知道大家发现没,上面的例子在拖拽开始,鼠标就一直处于这种“可放置”状态,不管是在放置目标外部还是内部,如下:,鼠标指针状态,这是因为设置了dragover属性,所以整个document都变成了可放置目标,都允许触发drop事件。,如果希望交互更加细腻,体验更好,那么在鼠标指示上也可以进一步的优化,可以在进入放置目标后才变成这种状态,实现如下:,效果如下(注意观察鼠标的变化):,拖拽过程中的鼠标变化,除此之外,还应该在drop结束后移除掉over属性。,这样就实现了一个完全通用的自定义 dragover效果,区区数十行,划重点,完整代码如下:,当然还少不了 CSS 的配合,同样重要。,你也可以查看在线链接:自定义 dragover (codepen.io)[1]或者自定义 dragover (juejin.cn)[2]。,以上就是自定义 dragover 效果的完整实现了,不算复杂,但也有一些小技巧,特别是借助了 CSS 的能力。其实在这一版实现之前,我还尝试过很多别的实现,但都不如这种方式简洁明了,下面总结一下:,当然,拖拽在页面中的交互细节还有很多,比如拖拽排序过程中的挤压动画效果,后面有空再研究吧,争取出一个通用的解决方案。,[1]自定义 dragover (codepen.io): https://codepen.io/xboxyan/pen/yLvjXdJ,[2]自定义 dragover (juejin.cn): https://code.juejin.cn/pen/7104250686161813540

© 版权声明

相关文章