拖拽排序的实现示例demo
文章说明
文章主要为了学习拖拽排序的实现思路,并且采用此示例效果来进一步理解Flip动画的使用
参考渡一前端袁老师的讲解视频
核心代码
页面源码,拖拽排序的实现代码并不复杂,但是可以很好的帮助学习该示例的实现思路和拖拽API的使用
html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拖拽排序</title>
<style>
* {
box-sizing: border-box;
}
.container {
margin: 100px auto auto;
width: 200px;
}
.container div {
height: 30px;
line-height: 30px;
margin: 10px 0;
background-color: chocolate;
border-radius: 10px;
color: #ffffff;
text-align: center;
}
.container .moving {
border: dashed 1px black;
background-color: #ffffff;
}
</style>
</head>
<body>
<div class="container">
<div draggable="true" class="item">1</div>
<div draggable="true" class="item">2</div>
<div draggable="true" class="item">3</div>
<div draggable="true" class="item">4</div>
<div draggable="true" class="item">5</div>
<div draggable="true" class="item">6</div>
</div>
<script src="flip.js"></script>
<script>
const container = document.getElementsByClassName("container")[0];
let dragElem = null;
let flip;
container.ondragstart = function (e) {
flip = new Flip(container.children, 0.5);
dragElem = e.target;
setTimeout(() => {
e.target.classList.add("moving");
}, 0);
}
container.ondragover = function (e) {
e.preventDefault();
}
container.ondragend = function (e) {
e.target.classList.remove("moving");
}
container.ondragenter = function (e) {
e.preventDefault();
if (e.target === container || dragElem === e.target) {
return;
}
const children = [...container.children];
const sourceIndex = children.indexOf(dragElem);
const targetIndex = children.indexOf(e.target);
if (sourceIndex > targetIndex) {
container.insertBefore(dragElem, e.target);
} else {
container.insertBefore(dragElem, e.target.nextElementSibling);
}
flip.play();
}
</script>
</body>
</html>
Flip工具类
javascript
class Flip {
children = null;
delay = 0;
constructor(children, delay = 1) {
this.children = children;
this.calculatePos();
this.delay = delay;
}
calculatePos(name = "first") {
const children = this.children;
for (let i = 0; i < children.length; i++) {
children[i][name] = children[i].getBoundingClientRect();
}
}
play() {
this.calculatePos("last");
const children = this.children;
for (let i = 0; i < children.length; i++) {
const first = children[i]["first"];
const last = children[i]["last"];
if (first.x !== last.x || first.y !== last.y) {
children[i].style.transform = `translateY(${first.y - last.y}px) translateX(${first.x - last.x}px)`;
setTimeout(() => {
children[i].style.transition = `transform ${this.delay}s`;
children[i].style.removeProperty("transform");
setTimeout(() => {
children[i].style.removeProperty("transition");
this.calculatePos();
}, this.delay * 1000);
}, 0);
}
}
}
}
示例效果展示
拖拽功能展示