html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html, body {
width: 100%;
height: 100%;
min-width: 1100px;
background-color: rgb(87, 202, 11);
}
.content {
border-radius: 5px;
color: #fff;
font-weight: bolder;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 30px 50px;
}
.list {
width: 130px;
flex: none;
background: rgb(212, 195, 109);
border-radius: 10px;
margin-right: 20px;
padding: 10px 0;
}
.item {
background-color: cornflowerblue;
width: 80px;
height: 45px;
line-height: 45px;
color: #fff;
font-size: 18px;
font-weight: bolder;
border-radius: 10px;
text-align: center;
cursor: pointer;
margin: 10px auto;
}
.courses-box {
display: flex;
align-items: center;
justify-content: center;
background-color: antiquewhite;
border-radius: 10px;
flex: none;
width: 900px;
height: 600px;
box-sizing: border-box;
padding: 30px;
}
.time-box {
width: 30px;
flex: none;
margin-right: 30px;
padding-top: 30px;
}
.time {
width: 30px;
height: 200px;
background-color: rgb(10, 164, 112);
border-radius: 10px;
margin-top: 15px;
/* 文字排列方向 */
writing-mode: vertical-lr;
text-align: center;
letter-spacing: 10px;
padding-left: 3px;
}
.day-box {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 10px;
}
.day {
width: 100%;
flex: none;
display: flex;
align-items: center;
justify-content: space-around;
}
.day span {
width: 80px;
height: 35px;
line-height: 35px;
margin-bottom: 10px;
background-color: rgb(10, 164, 112);
border-radius: 5px;
text-align: center;
}
.courses {
flex: 1;
width: 100%;
background-color: rgb(10, 164, 112);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: space-around;
padding: 10px;
}
.course-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
.course {
width: 90px;
height: 50px;
background-color: beige;
margin: 5px 0;
border-radius: 5px;
display: flex;
align-items: center;
}
.course:nth-child(4) {
margin-bottom: 15px;
}
.drag-over {
background-color: rgb(159, 69, 69);
}
</style>
</head>
<body>
<div class="content">
<div class="list" data-allowed="move">
<!-- draggable为true元素才能拖拽 -->
<div class="item" draggable="true" data-effect="copy">语文</div>
<div class="item" draggable="true" data-effect="copy">数学</div>
<div class="item" draggable="true" data-effect="copy">英语</div>
<div class="item" draggable="true" data-effect="copy">科学</div>
<div class="item" draggable="true" data-effect="copy">体育</div>
<div class="item" draggable="true" data-effect="copy">地理</div>
<div class="item" draggable="true" data-effect="copy">历史</div>
<div class="item" draggable="true" data-effect="copy">物理</div>
</div>
<div class="courses-box">
<div class="time-box">
<div class="time">上午</div>
<div class="time">下午</div>
</div>
<div class="day-box">
<div class="day">
<span>星期一</span>
<span>星期二</span>
<span>星期三</span>
<span>星期四</span>
<span>星期五</span>
<span>星期六</span>
<span>星期日</span>
</div>
<div class="courses"></div>
</div>
</div>
</div>
<script src="./drag.js"></script>
</body>
</html>
js
const content = document.querySelector('.content');
const coursesDom = document.querySelector('.courses');
const courses = new Array(7).fill({
morning: new Array(4).fill(''),
afternoon: new Array(4).fill(''),
})
const renderCourses = () => {
courses.forEach((dayCourse) => {
const { morning, afternoon } = dayCourse;
const div = document.createElement('div');
div.classList.add('course-box');
[...morning, ...afternoon].forEach((course) => {
const span = document.createElement('span');
span.textContent = course;
span.classList.add('course');
span.dataset.allowed = 'copy';
div.appendChild(span);
});
coursesDom.appendChild(div);
});
}
renderCourses();
const clearStyle = () => {
const doms = document.querySelectorAll('.drag-over');
doms.forEach((dom) => {
dom.classList.remove('drag-over');
});
}
// 当前在拖拽的元素变量
let source = null;
content.ondragstart = (e) => {
// e.target为当前拖拽的元素
console.log('srart', e.target);
// 改变鼠标样式为copy样式,为一个加号
e.dataTransfer.effectAllowed = e.target.dataset.effect; // 取值:move、copy等
source = e.target;
};
content.ondragover = function(e) {
e.preventDefault();
// e.target为当前停留的元素,不停触发
console.log('over', e.target);
};
const findParentNode = (node) => {
while(node) {
if (node.dataset && node.dataset.allowed) {
return node;
}
node = node.parentNode;
}
}
content.ondragenter = (e) => {
e.preventDefault();
// e.target为当前进入的元素
console.log('enter', e.target);
clearStyle();
const node = findParentNode(e.target);
if (!node) {
return;
}
if (source.dataset.effect === node.dataset.allowed) {
e.target.classList.add('drag-over');
}
};
content.ondragleave = (e) => {
// e.target为当前离开的元素
console.log('leave', e.target);
};
content.ondrop = (e) => {
clearStyle();
// e.target松开鼠标时所在的元素,这个方法能被触发,要确保ondragover中 e.preventDefault();因为元素默认是不允许其他元素拖到上面的
console.log('drop', e.target);
if (source.dataset.effect === e.target.dataset.allowed) {
if (source.dataset.effect === 'copy') {
e.target.innerHTML = '';
const dom = source.cloneNode(true);
dom.dataset.effect = 'move';
e.target.appendChild(dom);
} else {
// 清空所有子元素
source.remove();
}
}
};
效果图