用html
+jq
实现元素的拖动效果
效果图如下:
将【item10】拖动到【item1】前面
直接上代码:
html部分
<ul id="sortableList">
<li id="item1" class="w1" draggable="true">Item 1</li>
<li id="item2" class="w2" draggable="true">Item 2</li>
<li id="item3" class="w3" draggable="true">Item 3</li>
<li id="item4" class="w1" draggable="true">Item 4</li>
<li id="item5" class="w1" draggable="true">Item 5</li>
<li id="item6" class="w2" draggable="true">Item 6</li>
<li id="item7" class="w3" draggable="true">Item 7</li>
<li id="item8" class="w1" draggable="true">Item 8</li>
<li id="item9" class="w2" draggable="true">Item 9</li>
<li id="item10" class="w3" draggable="true">Item 10</li>
</ul>
js部分
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const sortableList = document.getElementById('sortableList');
const items = sortableList.querySelectorAll('li');
items.forEach((item) => {
item.addEventListener('dragstart', dragStart);
item.addEventListener('dragover', dragOver);
item.addEventListener('drop', drop);
item.addEventListener('dragenter', dragEnter);
item.addEventListener('dragleave', dragLeave);
});
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
// setTimeout(() => {
// e.target.classList.add('hide');
// }, 0);
console.log('Drag started:', e.target.id);
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add('over');
console.log('Drag over:', e.target.id);
}
function dragEnter(e) {
e.preventDefault();
console.log('Drag enter:', e.target.id);
}
function dragLeave(e) {
e.target.classList.remove('over');
console.log('Drag leave:', e.target.id);
}
function drop(e) {
e.preventDefault();
const draggedItemId = e.dataTransfer.getData('text/plain');
const draggedItem = document.getElementById(draggedItemId);
const targetItem = e.target;
if (targetItem !== draggedItem) {
const targetIndex = Array.from(items).indexOf(targetItem);
const draggedIndex = Array.from(items).indexOf(draggedItem);
if (targetIndex > draggedIndex) {
targetItem.parentNode.insertBefore(
draggedItem,
targetItem.nextSibling
);
} else {
targetItem.parentNode.insertBefore(draggedItem, targetItem);
}
}
e.target.classList.remove('over');
draggedItem.classList.remove('hide');
console.log('Drop:', e.target.id);
console.log('在这里加检查宽度方法');
checkWidth();
}
});
// 检查宽度
function checkWidth(first = true) {
//清空空白块
if (first) $('#sortableList li.box').remove();
//盒子宽度
let boxWidth = document.getElementById('sortableList').offsetWidth;
//当前li行的宽度
let rowLiWidth = 0;
//循环li
for (let i = 0; i < $('#sortableList li').length; i++) {
var outerWidthWithMargin = $('#sortableList li')
.eq(i)
.outerWidth(true);
var itemWidth = parseFloat(outerWidthWithMargin.toFixed(2));
console.log(i, rowLiWidth, itemWidth);
//当前li行的宽度+当前项宽度
let RAW = rowLiWidth + itemWidth;
//如果当前li行的宽度+当前项宽度大于盒子宽度,则添加空白块,并重新计算。
//3是容错宽度。
if (
RAW >= boxWidth ||
(RAW - boxWidth >= -3 && RAW - boxWidth <= 3)
) {
//宽度大于盒子宽度,则添加空白块,并重新计算。
if (RAW > boxWidth) {
let thisWidth = boxWidth - rowLiWidth;
if (thisWidth > 3) {
$('#sortableList li')
.eq(i)
.before(`<li class="box" style="width:${thisWidth}px"></li>`);
rowLiWidth = 0; //重新计算。
checkWidth(false);
break;
}
}
rowLiWidth = 0; //重新计算。
} else {
rowLiWidth += itemWidth;
}
if (i == $('#sortableList li').length - 1) {
let thisWidth = boxWidth - rowLiWidth;
$('#sortableList li')
.eq(i)
.after(`<li class="box" style="width:${thisWidth}px"></li>`);
break;
}
}
}
</script>
css部分
<style>
* {
box-sizing: border-box;
}
#sortableList {
list-style-type: none;
padding: 0;
display: flex;
flex-wrap: wrap;
position: relative;
}
#sortableList:after {
border-top: none;
border-left: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
}
#sortableList:after,
#sortableList li:after {
content: '';
border: 1px solid #eee;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
}
#sortableList li:after {
border-right: none;
border-bottom: none;
}
#sortableList li {
padding: 8px;
background-color: #fff;
cursor: move;
position: relative;
}
#sortableList li.box {
background-color: #fff;
}
#sortableList li.over {
border: 2px dashed #000;
}
#sortableList li.w1 {
width: 20%;
}
#sortableList li.w2 {
width: 30%;
}
#sortableList li.w3 {
width: 50%;
}
#sortableList li.hide {
display: none;
}
</style>
完整版代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<style>
* {
box-sizing: border-box;
}
#sortableList {
list-style-type: none;
padding: 0;
display: flex;
flex-wrap: wrap;
position: relative;
}
#sortableList:after {
border-top: none;
border-left: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
}
#sortableList:after,
#sortableList li:after {
content: '';
border: 1px solid #eee;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
}
#sortableList li:after {
border-right: none;
border-bottom: none;
}
#sortableList li {
padding: 8px;
background-color: #fff;
cursor: move;
position: relative;
}
#sortableList li.box {
background-color: #fff;
}
#sortableList li.over {
border: 2px dashed #000;
}
#sortableList li.w1 {
width: 20%;
}
#sortableList li.w2 {
width: 30%;
}
#sortableList li.w3 {
width: 50%;
}
#sortableList li.hide {
display: none;
}
</style>
</head>
<body>
<ul id="sortableList">
<li id="item1" class="w1" draggable="true">Item 1</li>
<li id="item2" class="w2" draggable="true">Item 2</li>
<li id="item3" class="w3" draggable="true">Item 3</li>
<li id="item4" class="w1" draggable="true">Item 4</li>
<li id="item5" class="w1" draggable="true">Item 5</li>
<li id="item6" class="w2" draggable="true">Item 6</li>
<li id="item7" class="w3" draggable="true">Item 7</li>
<li id="item8" class="w1" draggable="true">Item 8</li>
<li id="item9" class="w2" draggable="true">Item 9</li>
<li id="item10" class="w3" draggable="true">Item 10</li>
</ul>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const sortableList = document.getElementById('sortableList');
const items = sortableList.querySelectorAll('li');
items.forEach((item) => {
item.addEventListener('dragstart', dragStart);
item.addEventListener('dragover', dragOver);
item.addEventListener('drop', drop);
item.addEventListener('dragenter', dragEnter);
item.addEventListener('dragleave', dragLeave);
});
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
// setTimeout(() => {
// e.target.classList.add('hide');
// }, 0);
console.log('Drag started:', e.target.id);
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add('over');
console.log('Drag over:', e.target.id);
}
function dragEnter(e) {
e.preventDefault();
console.log('Drag enter:', e.target.id);
}
function dragLeave(e) {
e.target.classList.remove('over');
console.log('Drag leave:', e.target.id);
}
function drop(e) {
e.preventDefault();
const draggedItemId = e.dataTransfer.getData('text/plain');
const draggedItem = document.getElementById(draggedItemId);
const targetItem = e.target;
if (targetItem !== draggedItem) {
const targetIndex = Array.from(items).indexOf(targetItem);
const draggedIndex = Array.from(items).indexOf(draggedItem);
if (targetIndex > draggedIndex) {
targetItem.parentNode.insertBefore(
draggedItem,
targetItem.nextSibling
);
} else {
targetItem.parentNode.insertBefore(draggedItem, targetItem);
}
}
e.target.classList.remove('over');
draggedItem.classList.remove('hide');
console.log('Drop:', e.target.id);
console.log('在这里加检查宽度方法');
checkWidth();
}
});
// 检查宽度
function checkWidth(first = true) {
//清空空白块
if (first) $('#sortableList li.box').remove();
//盒子宽度
let boxWidth = document.getElementById('sortableList').offsetWidth;
//当前li行的宽度
let rowLiWidth = 0;
//循环li
for (let i = 0; i < $('#sortableList li').length; i++) {
var outerWidthWithMargin = $('#sortableList li')
.eq(i)
.outerWidth(true);
var itemWidth = parseFloat(outerWidthWithMargin.toFixed(2));
console.log(i, rowLiWidth, itemWidth);
//当前li行的宽度+当前项宽度
let RAW = rowLiWidth + itemWidth;
//如果当前li行的宽度+当前项宽度大于盒子宽度,则添加空白块,并重新计算。
//3是容错宽度。
if (
RAW >= boxWidth ||
(RAW - boxWidth >= -3 && RAW - boxWidth <= 3)
) {
//宽度大于盒子宽度,则添加空白块,并重新计算。
if (RAW > boxWidth) {
let thisWidth = boxWidth - rowLiWidth;
if (thisWidth > 3) {
$('#sortableList li')
.eq(i)
.before(`<li class="box" style="width:${thisWidth}px"></li>`);
rowLiWidth = 0; //重新计算。
checkWidth(false);
break;
}
}
rowLiWidth = 0; //重新计算。
} else {
rowLiWidth += itemWidth;
}
if (i == $('#sortableList li').length - 1) {
let thisWidth = boxWidth - rowLiWidth;
$('#sortableList li')
.eq(i)
.after(`<li class="box" style="width:${thisWidth}px"></li>`);
break;
}
}
}
</script>
</body>
</html>