HTML5拖拽API学习 托拽排序和可托拽课程表

embedded/2024/11/18 19:50:00/

文章目录

      • 前言
      • 拖拽API核心概念
      • 拖拽式使用流程
      • 例子
      • 注意事项
      • 综合例子🌰 可拖拽课程表
      • 拖拽排序

在这里插入图片描述

前言

前端拖拽功能让网页元素可以通过鼠标或触摸操作移动。HTML5 提供了标准的拖拽API,简化了拖放操作的实现。以下是拖拽API的基本使用指南:

拖拽API核心概念

  1. draggable属性:设置元素的draggable="true"属性,允许用户拖动该元素。
    <div draggable="true">可拖动元素</div>
  1. dragstart事件:拖动开始时触发,可以设置拖动数据。
    const draggableElement = document.querySelector('div');draggableElement.addEventListener('dragstart', (event) => {event.dataTransfer.setData('text/plain', '拖动数据');});
  1. dragover事件:拖动元素在目标区域上方时触发,需要调用event.preventDefault()以允许放置。
javascript">    const dropZone = document.querySelector('#dropZone');dropZone.addEventListener('dragover', (event) => {event.preventDefault(); // 允许放置});
  1. drop事件:拖动元素放置到目标区域时触发,可以获取拖动数据。
    dropZone.addEventListener('drop', (event) => {event.preventDefault();const data = event.dataTransfer.getData('text/plain');console.log('放置的数据:', data);});
  1. dragend事件:拖动操作结束时触发,用于清理拖动状态或重置样式。
draggableElement.addEventListener('dragend', () => {draggableElement.style.backgroundColor = ''; // 重置样式});

拖拽式使用流程

  1. 设置可拖拽元素:在HTML中为元素添加draggable="true"属性。
  2. 处理拖拽开始事件:在dragstart事件中设置拖拽数据。
  3. 设置目标区域:通过dragover事件处理,允许放置操作。
  4. 处理放置事件:在drop事件中获取数据并处理放置逻辑。
  5. 清理拖拽操作:在dragend事件中清理元素样式或状态。

例子

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>拖拽示例</title><style>#dragElement {width: 100px; height: 100px; background-color: skyblue; cursor: move; text-align: center; line-height: 100px;}#dropZone {width: 300px; height: 300px; border: 2px dashed #aaa; margin-top: 50px; text-align: center; line-height: 300px; color: #888;}</style></head><body><div id="dragElement" draggable="true">拖我</div><div id="dropZone">在这里放置</div><script>javascript">const dragElement = document.getElementById('dragElement');const dropZone = document.getElementById('dropZone');dragElement.addEventListener('dragstart', (event) => {console.log('拖拽开始');event.dataTransfer.setData('text/plain', 'Hello, 拖拽');event.target.style.backgroundColor = 'orange';});dropZone.addEventListener('dragover', (event) => {console.log('拖拽进入');event.preventDefault();});dropZone.addEventListener('drop', (event) => {console.log('拖拽放下');event.preventDefault();const data = event.dataTransfer.getData('text/plain');dropZone.innerHTML = `放置了:${data}`;});dragElement.addEventListener('dragend', (event) => {console.log('拖拽结束');event.target.style.backgroundColor = 'skyblue';});</script></body></html>

注意事项

  • 兼容性:大多数现代浏览器支持HTML5拖拽API,但老旧浏览器如IE8及以下不支持。
  • 样式:可以通过设置样式增强用户体验,如改变光标或透明度。
  • 文件拖放:HTML5还支持拖拽文件到浏览器特定区域,可以通过event.dataTransfer.files获取文件数据。

综合例子🌰 可拖拽课程表

<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>可拖拽课程表</title><style>body {margin: 0;padding: 20px;}.schedule-container {display: flex;gap: 20px;max-width: 1400px;margin: 0 auto;}.schedule-table {flex: 1;display: grid;grid-template-columns: 100px repeat(7, 1fr);gap: 2px;background-color: #fff;border: 1px solid #ddd;height: fit-content;}.time-column {background-color: #f8f9fa;padding: 10px;text-align: center;font-weight: bold;}.header-row {background-color: #f8f9fa;padding: 10px;text-align: center;font-weight: bold;}.course-list {width: 250px;padding: 15px;border: 1px solid #ddd;background-color: #f8f9fa;border-radius: 8px;height: fit-content;}.course-list h3 {margin-top: 0;margin-bottom: 15px;color: #333;}#available-courses {display: flex;flex-direction: column;gap: 10px;}</style></head><body><div class="schedule-container"><div class="schedule-table"><!-- 表头 --><div class="header-row">时间</div><div class="header-row">周一</div><div class="header-row">周二</div><div class="header-row">周三</div><div class="header-row">周四</div><div class="header-row">周五</div><div class="header-row">周六</div><div class="header-row">周日</div></div><!-- 课程列表 --><div class="course-list"><h3>可选课程</h3><div id="available-courses"><!-- 这里会通过JavaScript动态生成可拖拽的课程 --></div></div></div><script src="tuozuaiApi.js"></script></body></html>
//tuozhaiApi.js
// 课程表拖拽功能实现const DragSchedule = {init() {this.scheduleTable = document.querySelector('.schedule-table');this.availableCourses = document.getElementById('available-courses');this.createTimeSlots();this.createSampleCourses();this.cells = document.querySelectorAll('.schedule-cell');this.courses = document.querySelectorAll('.course-item');this.bindEvents();this.loadScheduleState();},createTimeSlots() {// 创建时间段(第一节课从8:00开始)const times = ['8:00-8:45', '8:55-9:40', '9:50-10:35', '10:45-11:30','13:30-14:15', '14:25-15:10', '15:20-16:05', '16:15-17:00'];times.forEach((time, index) => {// 添加时间列const timeCell = document.createElement('div');timeCell.className = 'time-column';timeCell.textContent = `${index + 1}节\n${time}`;this.scheduleTable.appendChild(timeCell);// 添加每一天的课程格子for (let day = 0; day < 7; day++) {const cell = document.createElement('div');cell.className = 'schedule-cell';cell.setAttribute('data-time', index);cell.setAttribute('data-day', day);this.scheduleTable.appendChild(cell);}});},createSampleCourses() {const sampleCourses = [{ id: 1, name: '高等数学', color: '#ff9999' },{ id: 2, name: '大学英语', color: '#99ff99' },{ id: 3, name: '程序设计', color: '#9999ff' },{ id: 4, name: '物理实验', color: '#ffff99' },{ id: 5, name: '体育课', color: '#ff99ff' }];sampleCourses.forEach(course => {const courseElement = document.createElement('div');courseElement.className = 'course-item';courseElement.setAttribute('data-course-id', course.id);courseElement.setAttribute('draggable', true); // 添加draggable属性courseElement.textContent = course.name;courseElement.style.backgroundColor = course.color;this.availableCourses.appendChild(courseElement);});},bindEvents() {// 为每个课程添加拖拽事件this.courses.forEach(course => {course.ondragstart = (e) => {e.target.classList.add('dragging');e.dataTransfer.setData('text/plain', e.target.getAttribute('data-course-id'));};course.ondragend = (e) => {e.target.classList.remove('dragging');};});// 为每个单元格添加放置事件this.cells.forEach(cell => {cell.ondragover = (e) => {e.preventDefault();e.currentTarget.classList.add('drag-over');};cell.ondragleave = (e) => {e.currentTarget.classList.remove('drag-over');};cell.ondrop = this.handleDrop.bind(this);});},saveScheduleState() {const scheduleState = {};this.cells.forEach((cell, index) => {const courseElement = cell.querySelector('.course-item');if (courseElement) {scheduleState[index] = courseElement.getAttribute('data-course-id');}});localStorage.setItem('scheduleState', JSON.stringify(scheduleState));},loadScheduleState() {const savedState = localStorage.getItem('scheduleState');if (savedState) {const scheduleState = JSON.parse(savedState);Object.entries(scheduleState).forEach(([cellIndex, courseId]) => {const cell = this.cells[cellIndex];const courseElement = document.querySelector(`[data-course-id="${courseId}"]`);if (cell && courseElement) {const newCourse = courseElement.cloneNode(true);newCourse.setAttribute('draggable', true);newCourse.ondragstart = (e) => {e.target.classList.add('dragging');e.dataTransfer.setData('text/plain', e.target.getAttribute('data-course-id'));};newCourse.ondragend = (e) => {e.target.classList.remove('dragging');};cell.appendChild(newCourse);}});}},handleDrop(e) {e.preventDefault();const cell = e.currentTarget;cell.classList.remove('drag-over');const courseId = e.dataTransfer.getData('text/plain');const courseElement = document.querySelector(`[data-course-id="${courseId}"]`);// 如果课程已经在其他单元格中,创建一个副本const newCourse = courseElement.cloneNode(true);newCourse.setAttribute('draggable', true);newCourse.ondragstart = (e) => {e.target.classList.add('dragging');e.dataTransfer.setData('text/plain', e.target.getAttribute('data-course-id'));};newCourse.ondragend = (e) => {e.target.classList.remove('dragging');};// 检查单元格是否已有课程if (cell.querySelector('.course-item')) {const existingCourse = cell.querySelector('.course-item');cell.removeChild(existingCourse);}cell.appendChild(newCourse);// 保存课程表状态this.saveScheduleState();}};// 添加更多样式const style = document.createElement('style');style.textContent = `.schedule-cell {min-height: 80px;border: 1px solid #ddd;padding: 8px;background-color: #fff;}.course-item {padding: 8px;margin: 4px;border-radius: 4px;cursor: move;color: #fff;text-shadow: 1px 1px 1px rgba(0,0,0,0.2);box-shadow: 2px 2px 4px rgba(0,0,0,0.1);}.dragging {opacity: 0.5;}.drag-over {background-color: #e9ecef;}.time-column {white-space: pre-line;font-size: 12px;}`;document.head.appendChild(style);// 初始化拖拽功能document.addEventListener('DOMContentLoaded', () => {DragSchedule.init();});

拖拽排序

<!DOCTYPE html><html lang="zh"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>拖拽排序示例</title><style>.sortable-list {width: 300px;margin: 20px auto;padding: 0;}.sortable-item {list-style: none;background-color: #f0f0f0;margin: 5px 0;padding: 10px 15px;border-radius: 4px;cursor: move;transition: background-color 0.3s;}.sortable-item.dragging {opacity: 0.5;background-color: #e0e0e0;}.sortable-item:hover {background-color: #e8e8e8;}</style></head><body><ul class="sortable-list"><li class="sortable-item" draggable="true">项目 1</li><li class="sortable-item" draggable="true">项目 2</li><li class="sortable-item" draggable="true">项目 3</li><li class="sortable-item" draggable="true">项目 4</li><li class="sortable-item" draggable="true">项目 5</li></ul><script>javascript">const sortableList = document.querySelector('.sortable-list');let draggingItem = null;// 为每个列表项添加拖拽事件监听器document.querySelectorAll('.sortable-item').forEach(item => {item.addEventListener('dragstart', handleDragStart);item.addEventListener('dragend', handleDragEnd);item.addEventListener('dragover', handleDragOver);item.addEventListener('drop', handleDrop);});function handleDragStart(e) {draggingItem = this;this.classList.add('dragging');// 设置拖拽效果e.dataTransfer.effectAllowed = 'move';e.dataTransfer.setData('text/plain', ''); // 必须调用setData才能在Firefox中触发drop}function handleDragEnd(e) {this.classList.remove('dragging');draggingItem = null;}function handleDragOver(e) {e.preventDefault();if (this === draggingItem) return;// 获取鼠标位置相对于当前项的位置const rect = this.getBoundingClientRect();const midY = rect.top + rect.height / 2;if (e.clientY < midY) {// 如果鼠标在元素上半部分,就插入到当前元素之前sortableList.insertBefore(draggingItem, this);} else {// 如果鼠标在元素下半部分,就插入到当前元素之后sortableList.insertBefore(draggingItem, this.nextSibling);}}function handleDrop(e) {e.preventDefault();}</script></body></html>

http://www.ppmy.cn/embedded/138617.html

相关文章

【计算机网络】TCP网络程序

一、服务端 1.tcpServer.hpp 此文件负责实现一个tcp服务器 #pragma once #include <iostream> #include <string> #include <cstring> #include <unistd.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h…

关于mysql中的锁

mysql中包含的锁分为&#xff1a; 一、全局锁 二、表锁 三、行锁 一、全局锁 全局锁的力度是最大的&#xff0c;全局锁对整个数据库实例加锁&#xff0c;加锁后整个实例就处于只读状态&#xff0c;后续的DML的写语句&#xff0c;DDL语句&#xff0c;已经更新操作的事务提交语句…

SQL注入注入方式(大纲)

SQL注入注入方式&#xff08;大纲&#xff09; 常规注入 通常没有任何过滤&#xff0c;直接把参数存放到SQL语句中。 宽字节注入 GBK 编码 两个字节表示一个字符ASCII 编码 一个字节表示一个字符MYSQL默认字节集是GBK等宽字节字符集 原理&#xff1a; 设置MySQL时错误配置…

MATLAB用CNN-LSTM神经网络的语音情感分类深度学习研究

全文链接&#xff1a;https://tecdat.cn/?p38258 在语音处理领域&#xff0c;对语音情感的分类是一个重要的研究方向。本文将介绍如何通过结合二维卷积神经网络&#xff08;2 - D CNN&#xff09;和长短期记忆网络&#xff08;LSTM&#xff09;构建一个用于语音分类任务的网络…

TKinter实现与Dash应用的同步启停控制

使用Python集成Tkinter和Dash&#xff1a;创建交互式数据可视化应用 在数据可视化项目中&#xff0c;我们经常需要结合传统GUI和现代Web可视化框架的优势。本文将介绍如何整合Tkinter和Dash&#xff0c;创建一个既有桌面应用界面&#xff0c;又能展示交互式图表的应用程序。 …

Spring纯注解开发

在我的另一篇文章中&#xff08;初识Spring-CSDN博客&#xff09;&#xff0c;讲述了Bean&#xff0c;以及通过xml方式定义Bean。接下来将讲解通过注解的方法管理Bean。 我们在创建具体的类的时候&#xff0c;可以直接在类的上面标明“注解”&#xff0c;以此来声明类。 1. 常…

MoneyPrinterTurbo - AI自动生成高清短视频

MoneyPrinterTurbo是一款基于AI大模型的开源软件&#xff0c;旨在通过一键操作帮助用户自动生成高清短视频。只需提供一个视频 主题或 **关键词** &#xff0c;就可以全自动生成视频文案、视频素材、视频字幕、视频背景音乐&#xff0c;然后合成一个高清的短视频。 ​ ​ 主要…

Vue中template模板报错

直接<v出现如下模板&#xff0c;出现如下错误 注意两个地方&#xff1a; 1.template里面加一个div标签 2.要写name值 如下图