之前在我的项目中用到了拖放排序,不过是用react-dnd实现的,因为集体还是比拟喜爱这种拖放的交互体验的,所以写了个小demo。

不废话,先看看最终实现的样子:

我称之为《鬼灭之圣诞之拖拽排序????》:)

用鬼灭的图做了个九宫格,可拖放任意一张调整九张图的程序。

实现过程

首先把页面构造和款式写好:

index.html

<div id="container">    <img draggable="true" src="./img/1.jpg">    <img draggable="true" src="./img/2.jpg">    <img draggable="true" src="./img/3.jpg">    <img draggable="true" src="./img/4.jpg">    <img draggable="true" src="./img/5.jpg">    <img draggable="true" src="./img/6.jpg">    <img draggable="true" src="./img/7.jpg">    <img draggable="true" src="./img/8.jpg">    <img draggable="true" src="./img/9.jpg"></div>

index.css

#container{    margin: 0 auto;    overflow: hidden;    width: 420px;}#container img{    width: 120px;    height: 120px;    object-fit: cover; //图片放弃原有尺寸比例,可能被裁剪    float: left;    border: 10px solid #ffffff;    cursor: move; //光标款式}
对于拖放

写排序功能前,须要先理解一下咱们拖放API:

在HTML5规范施行之前,拖拽也是被宽泛应用的,web开发者将click、mouseover,mousemove组合起来实现拖放逻辑,过程略显冗余和繁琐。

在HTML5中,拖放成为了规范的一部分,只需将元素draggable属性设为true,就可能拖放元素。拖放流程大抵如下图(省略了dragleave和dragexit):

HTML5不仅仅定义了拖拽的事件类型,还在事件对象中标准了一个重量级的对象:dataTransfer。借助它能够实现数据传输拖拽图案设定拖拽文件上传,可通过event.dataTransfer来拜访该对象。

增加拖放事件

因为拖动是实时的,所以没有应用drop而是应用了dragover。并且用一个变量来保留以后拖动的元素。这里应用事件委托,间接应用#container来监听。

const node = document.querySelector('#container');let dragging = null; //拖动的对象//拖拽开始node.ondragstart = (e) => {    //firefox设置了setData后元素能力拖动    e.dataTransfer.setData('for-firefox', 'hello')     dragging = e.target;    let offsetX = parseFloat(getComputedStyle(e.target).width)/2;    let offsetY = parseFloat(getComputedStyle(e.target).height)/2;    e.dataTransfer.setDragImage(e.target ,offsetX,offsetY);}//被拖拽的元素在某个元素停留时node.ondragover = (e) => {    e.preventDefault();    let target = e.target; //停留的某个元素    if (target.nodeName === "IMG" && target !== dragging) {        if (getIndex(dragging) < getIndex(target)) {            target.parentNode.insertBefore(dragging, target.nextSibling);        } else {            target.parentNode.insertBefore(dragging, target);        }    }}//获取元素在父元素中的索引function getIndex(el) {    let index = 0;    if (!el || !el.parentNode) {        return -1;    }    while (el && (el = el.previousElementSibling)) {        index++;    }    return index;}

OK,这样根本的排序就做好了,如果感觉图片切换过于僵硬的话,还能够增加一些动画成果,让过渡再平滑一些。