拖拽API
更新: 2025/3/23 21:32:41
课程表
语文
数学
英语
音乐
政治
历史
体育
星期一 | 星期二 | 星期三 | 星期四 | 星期五 | 星期六 | 星期日 | |
---|---|---|---|---|---|---|---|
上午 | |||||||
下午 | |||||||
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>定制课程表</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<h1>课程表</h1>
<div class="container">
<div class="left" data-drop="move">
<!-- draggable设置为true就可以实现拖拽 -->
<div data-effect="copy" draggable="true" class="color1 item">语文</div>
<div data-effect="copy" draggable="true" class="color2 item">数学</div>
<div data-effect="copy" draggable="true" class="color3 item">英语</div>
<div data-effect="copy" draggable="true" class="color4 item">音乐</div>
<div data-effect="copy" draggable="true" class="color5 item">政治</div>
<div data-effect="copy" draggable="true" class="color6 item">历史</div>
<div data-effect="copy" draggable="true" class="color7 item">体育</div>
</div>
<div class="right">
<table>
<!-- 列的分组 -->
<colgroup>
<col />
<col />
<col />
<col />
<col />
<col />
<col />
<col />
</colgroup>
<thead>
<tr>
<td></td>
<th>星期一</th>
<th>星期二</th>
<th>星期三</th>
<th>星期四</th>
<th>星期五</th>
<th>星期六</th>
<th>星期日</th>
</tr>
</thead>
<tbody>
<tr>
<th rowspan="4" class="span">上午</th>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
</tr>
<tr>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
</tr>
<tr>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
</tr>
<tr>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
</tr>
<tr>
<td colspan="8" class="noborder"></td>
</tr>
<tr>
<th rowspan="4" class="span">下午</th>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
</tr>
<tr>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
</tr>
<tr>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
</tr>
<tr>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
<td data-drop="copy"></td>
</tr>
</tbody>
</table>
</div>
</div>
<script src="./index.js"></script>
</body>
</html>
js
// 这里我们使用事件委托来在父元素上注册事件
const container = document.querySelector(".container");
let source;
// 只触发一次,事件源e是拖动的那个元素
container.ondragstart = (e) => {
e.dataTransfer.effectAllowed = e.target.dataset.effect; //设置鼠标样式,我们自定义一个属性,用来表示是拖进(copy)还是拖出(move)
source = e.target;
};
//会不断触发,事件源e是放置位置的元素
container.ondragover = (e) => {
e.preventDefault(); // 阻止默认事件,因为div等是不允许元素有元素放置其上的
// console.log('over', e.target);
};
function clearDropStyle() {
document.querySelectorAll(".drop-over").forEach((node) => {
node.classList.remove("drop-over");
});
}
// 看背景颜色是否变化,不仅要看自身,也要看父元素
function getDropNode(node) {
while (node) {
if (node.dataset && node.dataset.drop) {
return node;
}
node = node.parentNode;
}
}
// 和ondragover很像,但是不会触发的很频繁,e指的是进入的元素
container.ondragenter = (e) => {
// 清除之前的drop-over
clearDropStyle();
const dropNode = getDropNode(e.target);
if (dropNode && dropNode.dataset.drop === e.dataTransfer.effectAllowed) {
// 该节点能够接受目前拖拽的节点
dropNode.classList.add("drop-over");
}
};
// 拖拽放手的事件
container.ondrop = (e) => {
clearDropStyle();
const dropNode = getDropNode(e.target);
if (dropNode && dropNode.dataset.drop === e.dataTransfer.effectAllowed) {
if (dropNode.dataset.drop === "copy") {
dropNode.innerHTML = "";
const cloned = source.cloneNode(true);
cloned.dataset.effect = "move";
dropNode.appendChild(cloned);
} else {
// move
source.remove();
}
}
};
//e是离开的元素
container.ondragleave = (e) => {
console.log("leave", e.target);
};
css
.container {
display: flex;
justify-content: center;
}
.container .left {
padding: 10px;
width: 80px;
background: #eee;
}
.container .left .item {
margin-bottom: 10px;
}
.item {
width: 100%;
line-height: 40px;
text-align: center;
cursor: move;
}
.color1 {
background: #f26395;
}
.color2 {
background: #62efab;
}
.color3 {
background: #ef7658;
}
.color4 {
background: #ffe868;
}
.color5 {
background: #80e3f7;
}
.color6 {
background: #d781f9;
}
.color7 {
background: #62efab;
}
.container .right {
background: #eee;
width: 800px;
margin-left: 10px;
padding: 10px;
}
.container .right table {
width: 100%;
}
.container .right td,
.container .right th {
border: 1px solid #999;
height: 33px;
padding: 8px;
text-align: center;
}
.container .right col:first-child {
width: 40px;
}
.container .right .span {
line-height: 40px;
}
.container .right thead td:first-child,
.container .right .noborder {
border: none;
}
.container .right th {
font-weight: normal;
background: #ccc;
}
.container .drop-over {
background: #666;
}