当前位置: 首页 > news >正文

【前端动效】原生js实现拖拽排课效果

目录

1. 效果展示

2. 效果分析

2.1 关键点

2.2 实现方法

3. 代码实现

3.1 html部分

3.2 css部分

3.3 js部分 

3.4 完整代码

4. 总结


1. 效果展示

如图所示,页面左侧有一个包含不同课程(如语文、数学等)的列表,页面右侧是一个表格,表示一周内每天的不同时间段。用户可以通过拖拽左侧的课程到右侧的时间表中,来安排课程。

 

2. 效果分析

目标:鼠标摁下左侧某一科目,拖拽到右侧某一位置放下,拖拽的课程就会嵌入到课表框当中

2.1 关键点

(1) 拖拽与放置逻辑的实现

(2) HTML与CSS布局的设计

2.2 实现方法

(1) 将拖拽过程分为 开始拖拽、允许放置、放置三部分分析。

(2) 页面主要由两部分组成——左侧是可拖动的课程项列表,右侧是一个表格,用于显示每周的时间安排。每个课程项都设定了 draggable = "true" 属性,使其可以被拖动。表格中的 <td> 元素(不包括第一列)是可以放置课程的目标区域。

(3) 通过 CSS 确保页面居中显示,并设置了 .box 容器的尺寸和边框。.left  和 .right 分别代表课程项列表和时间表的位置和大小。

3. 代码实现

接下来我会一步一步解说每段关键代码的含义。

3.1 html部分

  <div class="box"><div class="left"><div class="yu" draggable="true">语文</div><div class="shu" draggable="true">数学</div><div class="ying" draggable="true">英语</div><div class="wu" draggable="true">物理</div><div class="hua" draggable="true">化学</div><div class="sheng" draggable="true">生物</div></div><div class="right"><table><tr><th>时间/星期</th><th>星期一</th><th>星期二</th><th>星期三</th><th>星期四</th><th>星期五</th></tr><tr><td>08:00-09:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>10:00-11:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>11:00-12:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>12:00-13:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>14:00-15:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>15:00-16:00</td><td></td><td></td><td></td><td></td><td></td></tr></table></div></div>

左侧是课程列表,  该部分包含六个 <div> 元素,每个元素代表一门课程(如语文、数学等),并赋予了 draggable = "true" 属性,这意味着这些课程项可以被拖动。

右侧是时间表,提供了五个工作日(周一至周五)和六个上课时段的时间框架,使得用户可以直观地安排每周的课程。

3.2 css部分

 .left {width: 150px;display: flex;flex-direction: column;justify-content: space-between;gap: .7rem;}.left > div {width: 100%;height: 50px;border: 1px solid black;text-align: center;line-height: 50px;font-weight: bold;letter-spacing: 4px;cursor: move;}.yu { background: lawngreen; }.shu { background: skyblue; }.ying { background: mediumslateblue; }.wu { background: aqua; }.hua { background: violet; }.sheng { background: navajowhite; }.right {width: 750px;height: 400px;overflow: auto;}

css部分没什么好说的,按照自己的喜好随意编写即可。

3.3 js部分 

const draggables = document.querySelectorAll('.left > div');
const droppables = document.querySelectorAll('.right td:not(:first-child)');

 获取所有可拖动的课程项 和 所有可放置课程的时间段单元格(不包括第一列)。

draggables.forEach(draggable => {draggable.addEventListener('dragstart', e => {e.dataTransfer.setData('text/plain', e.target.className);e.dataTransfer.dropEffect = 'move';});});

拖拽开始::当用户开始拖动一个课程项时,浏览器触发 dragstart 事件。在这个事件处理函数中,我们使用 setData 方法将被拖拽元素的类名作为数据存储在 Datatransfer 对象中。同时,设置drapEffect 属性为 ‘move’,以表明这是一个移动操作。

droppables.forEach(droppable => {droppable.addEventListener('dragover', e => {e.preventDefault();e.dataTransfer.dropEffect = 'move';});
});

允许放置: 当拖拽元素经过目标单元格时,浏览器会触发 dragover 事件。默认情况下,浏览器会阻止这个事件,所以我们需要调用 preventDefault() 来允许放置。同样地,我们设置 dropEffect为 ‘move’,以便与 dragstart 中的设置相匹配。

droppable.addEventListener('drop', e => {e.preventDefault();const draggedItemClass = e.dataTransfer.getData('text/plain');const draggedItem = document.querySelector(`.${draggedItemClass}`);if (e.target.tagName === 'TD') {e.target.textContent = draggedItem.textContent;e.target.style.backgroundColor = window.getComputedStyle(draggedItem).backgroundColor;}
});

放置:当用户释放鼠标按钮,拖拽元素被放置到目标单元格时,浏览器触发 drap 事件。在这个事件处理函数中,我们获取之前存储的数据(即课程项的类名),找到对应的课程项,并将其内容和背景颜色复制到目标单元格中。

3.4 完整代码

<!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><style>body {margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #f0f0f0;}.box {width: 1000px;height: 600px;border: 1px solid red;display: flex;justify-content: space-between;align-items: center;padding: 20px;box-sizing: border-box;}.left {width: 150px;display: flex;flex-direction: column;justify-content: space-between;gap: .7rem;}.left > div {width: 100%;height: 50px;border: 1px solid black;text-align: center;line-height: 50px;font-weight: bold;letter-spacing: 4px;cursor: move;}.yu { background: lawngreen; }.shu { background: skyblue; }.ying { background: mediumslateblue; }.wu { background: aqua; }.hua { background: violet; }.sheng { background: navajowhite; }.right {width: 750px;height: 400px;overflow: auto;}table {width: 100%;border-collapse: collapse;}th, td {width: 120px;height: 50px;border: 1px solid black;text-align: center;}td {cursor: pointer;}</style>
</head>
<body><div class="box"><div class="left"><div class="yu" draggable="true">语文</div><div class="shu" draggable="true">数学</div><div class="ying" draggable="true">英语</div><div class="wu" draggable="true">物理</div><div class="hua" draggable="true">化学</div><div class="sheng" draggable="true">生物</div></div><div class="right"><table><tr><th>时间/星期</th><th>星期一</th><th>星期二</th><th>星期三</th><th>星期四</th><th>星期五</th></tr><tr><td>08:00-09:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>10:00-11:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>11:00-12:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>12:00-13:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>14:00-15:00</td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>15:00-16:00</td><td></td><td></td><td></td><td></td><td></td></tr></table></div></div><script>// 获取所有可拖动的课程项const draggables = document.querySelectorAll('.left > div');// 获取所有可放置课程的时间段单元格(不包括第一列)const droppables = document.querySelectorAll('.right td:not(:first-child)');// 添加拖拽开始事件监听器draggables.forEach(draggable => {draggable.addEventListener('dragstart', e => {e.dataTransfer.setData('text/plain', e.target.className);e.dataTransfer.dropEffect = 'move';});});// 添加拖拽进入和放置事件监听器droppables.forEach(droppable => {droppable.addEventListener('dragover', e => {e.preventDefault();e.dataTransfer.dropEffect = 'move';});droppable.addEventListener('drop', e => {e.preventDefault();const draggedItemClass = e.dataTransfer.getData('text/plain');const draggedItem = document.querySelector(`.${draggedItemClass}`);if (e.target.tagName === 'TD') {e.target.textContent = draggedItem.textContent;e.target.style.backgroundColor = window.getComputedStyle(draggedItem).backgroundColor;}});});</script>
</body>
</html>

 

4. 总结

以上即是实现拖拽排课动效的全部内容。如果对您有所帮助,不妨点赞、关注+收藏,下次不迷路😀。

更多前端动效点击下方链接↓ ↓ ↓

前端动效_借来一夜星光的博客-CSDN博客

http://www.lryc.cn/news/519887.html

相关文章:

  • C#使用OpenTK绘制3D可拖动旋转图形三棱锥
  • 排序的本质、数据类型及算法选择
  • Python的列表基础知识点(超详细流程)
  • HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现
  • 【Ubuntu与Linux操作系统:一、Ubuntu安装与基本使用】
  • React 元素渲染
  • 【2024年华为OD机试】 (C卷,100分)- 括号匹配(Java JS PythonC/C++)
  • 解锁企业数字化转型新力量:OpenCoze(开源扣子)
  • 【网络云SRE运维开发】2025第2周-每日【2025/01/12】小测-【第12章 rip路由协议】理论和实操考试题解析
  • 【微服务】8、分布式事务 ( XA 和 AT )
  • CVE-2025-22777 (CVSS 9.8):WordPress | GiveWP 插件的严重漏洞
  • TypeScript Jest 单元测试 搭建
  • 基于 SSH 的任务调度系统
  • filestream安装使用全套+filebeat的模块用法
  • java项目之房屋租赁系统源码(springboot+mysql+vue)
  • sap mm学习笔记
  • 代码随想录_链表
  • EF Code 并发控制
  • ceph fs status 输出详解
  • FFmpeg Muxer HLS
  • 如何用SQL语句来查询表或索引的行存/列存存储方式|OceanBase 用户问题集锦
  • 回归预测 | MATLAB实GRU多输入单输出回归预测
  • 【OpenGL/Assimp】渲染模型、半透明材质与封装光源
  • pandas与sql对应关系【帮助sql使用者快速上手pandas】
  • Linux WEB漏洞
  • 音视频入门基础:RTP专题(2)——使用FFmpeg命令生成RTP流
  • 大语言模型预训练、微调、RLHF
  • vue3后台系统动态路由实现
  • 解决idea中无法拖动tab标签页的问题
  • WMS仓库管理系统,Vue前端开发,Java后端技术源码(源码学习)