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

用两种不同的姿势实现拖拽排序

时间:2023-04-05 18:25:40 HTML5

前言鲁迅说:“你的技术不行,那你的姿势就应该多一些。”公司项目最近给侧边栏添加了拖拽排序效果,类似下面的效果(鲁迅:不是我底),是不是下面这张图?:拖拽拖拽排序不好意思说上图不是作者写的我,不然我还能把它炸了。代码我没看,但是你闭着眼睛也能猜到你用的是html5的drag系列api。相关API可以参考MDN上的介绍。让我复制文档并做一个介绍。拖动事件(每隔几百毫秒)。dragstart:当用户开始拖动元素或选择的文本时,将触发dragstart事件。一般拖拽元素的样式都是在这个action中处理的。dragend:拖动操作结束时触发,即鼠标操作松开。dragenter:当a被拖入b时触发。dragover:拖动过程中连续触发。dragexit:当元素没有被拖动时。dragleave:a拖到b,不松开鼠标,再拖到c,离开b时触发。drop:当一个元素或者选中的文本被拖拽释放到一个有效的释放目标位置时,上面大部分是处??理样式之类的。官方也举例排除了drag和dragoverBigfamily这两个trigger,大致顺序如下:首先,我肯定已经实现了效果,如下图:简单介绍下流程。首先需要确定的是效果应该是什么。比如我把a拖到b上,b能明显感觉到,“啊,有什么奇怪的东西进入了我的身体”。但是b不知道a是想在前面还是在后面……这时候你就会发现问题了,对吧!问题:“a和b哪个在上面,哪个在下面?”所以我们一开始要约定一个规范,把最上面的a拖到最下面的b,然后把a放在b下面,否则,就把最下面的a拖到b上面,然后把a放在b上面~首先,我需要这四个对象:letdragObj,enterObj,dragIndex,enterIndex;//dragObj是拖动对象a,整个拖动过程是不会改变的//enterObj最后进入对象b,在drop中就可以得到//dragIndexalistinthesubscript//enterIndexb是list中的下标通过比较dragIndex和enterIndex的大小关系确定a和b的大小,剩下的就是对dom进行操作了:if(dragIndexenterIndex){dragObj.remove();enterObj.before(dragObj);}是不是很简单?效果预览(chrome下查看)源码实现比较好--mouse直接看效果,也可以做个对比:预览效果用到的API:onmousedown,onmousemove,onmouseup,其实你应该用过这些或多或少,但我会在这里做一个粗略的介绍:onmousedown:当鼠标键点击当前元素时,会触发mousedown事件。有人问,这个和click有什么区别?不同的是click=mousedown+mouseup,然后点击鼠标左键触发,mousedown会在点击鼠标时触发。onmousemove:当用户在当前元素上移动鼠标时,会触发mousemove事件,即“拖动元素”。onmouseup:当用户在当前元素上松开鼠标按键时,会触发mouseup事件。整个实现过程也比上面那个好,一个复杂很多,它和drag不同,drag本身可以感知元素从a移动到b或者从b离开,但是鼠标事件不能。拖动的时候注意这样一个列表:假设我点击“小强”,“小强”是我选中的,如何实现拖动的效果呢?没有拖动元素本身这样的事情。我能做的就是动态改变它的位置,也就是在onmousemove的时候动态改变,改变元素的位置,不影响其他元素的排列,也就是绝对的。首先实现拖动的效果,大概是这样的://记录onmousedown时的必要信息,将小强的位置改为absoluteconststartY=event.clientY;//记录鼠标在y轴上移动的距离inonmousemove,如果是横向运行,则为xconstcurrentTop=parseInt(startTop)+(moveY-startY);这个基本的拖动问题就解决了,元素至少可以拖动了。这里需要注意的是只有“小强”的位置是绝对的,此时“小明”会被小强覆盖,所以我们这里需要一个元素“占用”:

--“你进来了吗?”--《你不是早就进来了吗》乘客系好安全带,我要开车了……理想的效果应该是这样的,把“小强”往下拉,和“小明”的距离当底部不到一半时,“小明”应该让位给“小强”。“小明”需要知道小强什么时候进来的,然后hold元素下移一个空格,说明此时小强已经在“小明”下面了:currentTop>itemHeight+itemHeight/2;记录高度真的没必要,我只需要记录“小强”当前被拖到的“数字”即可:currentIndex=Math.ceil((currentTop-itemHeight/2)/itemHeight);只要在onmousedown与当前比较时得到“小强”的“索引”,只要两者不同,就需要移动hold的位置,hold元素的位置受当前索引:if(previousIndex!==currentIndex){//...}这里省略的代码都是dom操作,就不过多解释了。这时候,我们对拖动的元素没有任何限制。可以将元素拖到框外。这绝对不可能。做一个限制:if(currentIndex<0){currentIndex=0;}elseif(currentIndex>listLength-1){currentIndex=listLength-1;}这样就不会限制用户的拖动操作,我们只需要控制索引即可,这样处理起来就方便多了。监听器需要在用户onmouseup时销毁:document.onmousemove=null;文档.onmouseup=null;注意$$和querySelectorAll得到的“数组”不是“数组”,它具有数组的一些特性,从下图我们可以知道它是一个NodeList,而不是一个数组。它有一个forEach方法,但是没有map、find等一系列方法,所以我们在使用的时候需要注意一下。有关详细信息,请参阅源代码。刚开始写的时候遇到了很多坑,尤其是操作dom的时候,尤其是上下拖拽的时候,来不及细说了。不好意思,今晚打到11:30,我心虚==,洗澡什么的,晚了。享受编码,热爱生活,拜拜~