前端原生js实现拖拽排课效果实例

2025-02-21 05:50

本文主要是介绍前端原生js实现拖拽排课效果实例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的...

1. 效果展示

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

前端原生js实现拖拽排课效果实例

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>
                <kHrlsktr>
                    <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;
        }
www.chinasem.cn        .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="yChina编程u" 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>
            编程China编程        <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>
                &javascriptlt;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. 总结

到此这篇关于前端原生js实现拖拽排课效果的文章就介绍到这了,更多相关原生js拖拽排课效果内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于前端原生js实现拖拽排课效果实例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153479

相关文章

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

Python实现PDF按页分割的技术指南

《Python实现PDF按页分割的技术指南》PDF文件处理是日常工作中的常见需求,特别是当我们需要将大型PDF文档拆分为多个部分时,下面我们就来看看如何使用Python创建一个灵活的PDF分割工具吧... 目录需求分析技术方案工具选择安装依赖完整代码实现使用说明基本用法示例命令输出示例技术亮点实际应用场景扩

MySQL多实例管理如何在一台主机上运行多个mysql

《MySQL多实例管理如何在一台主机上运行多个mysql》文章详解了在Linux主机上通过二进制方式安装MySQL多实例的步骤,涵盖端口配置、数据目录准备、初始化与启动流程,以及排错方法,适用于构建读... 目录一、什么是mysql多实例二、二进制方式安装MySQL1.获取二进制代码包2.安装基础依赖3.清