js实现拖拽功能
基于onMouseDown 、onMouseMove 、onMouseUp
使用 mousedown、mousemove 和 mouseup 事件来实现拖拽的基本思路是:
-
在
mousedown事件中,开始追踪拖拽操作并记录鼠标按下的位置。 -
在
mousemove事件中,根据鼠标的移动,更新被拖拽元素的位置。 -
在
mouseup事件中,停止拖拽操作,清除事件监听器,以及执行必要的清理操作。
以下是一些关键的步骤和注意事项:
实现拖拽的步骤:
-
在元素上监听
mousedown事件。当鼠标按下时,标记拖拽操作的开始。 -
在
mousedown事件处理程序中,记录鼠标按下时的初始位置(通常是相对于被拖拽元素的偏移量)。这将帮助你计算鼠标相对于元素的位置。 -
添加
mousemove事件监听器。在mousemove事件处理程序中,计算鼠标位置的变化,并根据变化来更新被拖拽元素的位置。 -
在
mouseup事件处理程序中,停止拖拽操作。清除mousemove和mouseup事件监听器,以确保不再处理鼠标移动和释放事件。
注意事项:
-
记录鼠标偏移:确保在
mousedown事件处理程序中记录鼠标按下时的初始位置。这将帮助你计算鼠标相对于元素的位置,以正确更新元素的位置。 -
防止文字选中:在拖拽元素上防止文字的选中,可以使用 CSS 的
user-select: none;样式或在mousedown事件中取消选择文字的默认行为。 -
移动边界:确保在
mousemove事件处理程序中更新元素的位置时,限制元素的移动范围,以防止它移出可见区域或父元素的边界。 -
清理:在
mouseup事件处理程序中,清除事件监听器,以避免内存泄漏或不必要的事件处理。 -
可访问性:考虑到可访问性,确保你的拖拽操作不会影响键盘用户。同时,确保在视觉上指示被拖拽元素的状态。
-
兼容性:确保你的拖拽实现在不同浏览器中正常工作,可能需要处理一些浏览器特定的问题或事件。
以下是一个简单的示例,演示了如何使用 mousedown、mousemove 和 mouseup 事件来实现一个可拖拽的元素:
const element = document.getElementById('draggableElement');
let isDragging = false;
let offsetX, offsetY;element.addEventListener('mousedown', (e) => {isDragging = true;offsetX = e.clientX - element.getBoundingClientRect().left;offsetY = e.clientY - element.getBoundingClientRect().top;element.style.cursor = 'grabbing';
});document.addEventListener('mousemove', (e) => {if (isDragging) {element.style.left = e.clientX - offsetX + 'px';element.style.top = e.clientY - offsetY + 'px';}
});document.addEventListener('mouseup', () => {isDragging = false;element.style.cursor = 'grab';
});
另外注意:
-
绝对定位: 通常,要实现拖拽效果,需要将元素设置为绝对定位,这样它可以脱离文档流,使其能够在页面上自由移动。这是拖拽操作的一个基本前提。
-
事件绑定: 拖拽元素的
mousedown事件和mousemove事件通常绑定在document上,而不是拖拽元素本身。这是因为拖拽元素可能会在页面上移动,而document会捕获全局的鼠标事件,确保无论鼠标在哪里释放,都可以正确处理拖拽操作。
<!DOCTYPE html>
<html>
<head><style>.draggable {width: 100px;height: 100px;background-color: lightblue;text-align: center;line-height: 100px;position: absolute;cursor: grab;}</style>
</head>
<body><div class="draggable" id="myElement">拖拽我</div><script>const element = document.getElementById('myElement');let isDragging = false;let offsetX, offsetY;element.addEventListener('mousedown', (e) => {isDragging = true;offsetX = e.clientX - element.getBoundingClientRect().left;offsetY = e.clientY - element.getBoundingClientRect().top;element.style.cursor = 'grabbing';});document.addEventListener('mousemove', (e) => {if (isDragging) {element.style.left = e.clientX - offsetX + 'px';element.style.top = e.clientY - offsetY + 'px';}});document.addEventListener('mouseup', () => {isDragging = false;element.style.cursor = 'grab';});</script>
</body>
</html>
Web API 提供了内置的拖放
Web API 提供了内置的拖放功能,主要涉及到以下事件和方法,以及一些注意事项:
拖放的思路:
-
ondragstart 事件: 当你想要元素成为可拖拽的源时,你可以监听
ondragstart事件,该事件在用户开始拖动元素时触发。你可以设置dataTransfer对象的数据,以便在拖放操作中传递信息。 -
ondragover 事件: 当你希望元素成为拖放目标时,你可以监听
ondragover事件,该事件在拖动元素悬停在目标元素上时触发。你可以通过ondragover事件的默认行为阻止拒绝拖放,或者通过 JavaScript 来决定是否接受拖放操作。 -
ondrop 事件: 当你希望在目标元素上接受拖放操作时,你可以监听
ondrop事件,该事件在用户完成拖放操作时触发。在ondrop事件处理程序中,你可以访问拖放数据,执行相应的操作,以及取消默认行为。
注意事项:
-
阻止默认行为: 如果你希望某个元素成为拖放源或目标,通常需要在
ondragstart和ondragover事件处理程序中使用event.preventDefault()阻止默认行为,以便正确处理拖放。 -
数据传递: 使用
dataTransfer对象来传递数据,这可以是文本、URL、自定义数据等。在ondragstart事件中设置数据,然后在ondrop事件中获取数据。 -
拖放目标状态: 使用
ondragenter和ondragleave事件来处理拖放目标的状态变化。这些事件在拖动元素进入和离开目标元素时触发。 -
拖放效果: 你可以使用
dataTransfer.effectAllowed和dataTransfer.dropEffect来指定拖放操作的效果,如移动、复制或链接。这有助于提供用户反馈。 -
跨浏览器兼容性: 考虑跨浏览器兼容性,因为不同浏览器可能会有一些差异,特别是在数据格式方面。
-
拖放元素样式: 为了提供视觉效果,你可以在
ondragstart事件中更改拖放元素的样式,以使用户知道它可以被拖动。
代码示例:
<!DOCTYPE html>
<html>
<head><style>.draggable {width: 100px;height: 100px;background-color: lightblue;text-align: center;line-height: 100px;position: absolute;cursor: grab;}.droppable {width: 200px;height: 200px;background-color: lightgray;position: absolute;top: 150px;left: 150px;}</style>
</head>
<body><divclass="draggable"draggable="true"ondragstart="dragStart(event)">拖拽我</div><divclass="droppable"ondragover="dragOver(event)"ondrop="drop(event)">放置区域</div><script>function dragStart(event) {event.dataTransfer.setData("text", event.target.id);event.target.style.cursor = 'grabbing';}function dragOver(event) {event.preventDefault();}function drop(event) {event.preventDefault();const data = event.dataTransfer.getData("text");const draggableElement = document.getElementById(data);event.target.appendChild(draggableElement);draggableElement.style.cursor = 'grab';}</script>
</body>
</html>
在这个示例中,创建了两个元素:一个可拖拽的元素(draggable)和一个接受拖动的目标元素(droppable)。draggable 元素被标记为可拖拽(draggable=“true”),并且定义了 ondragstart 事件处理程序,它在拖拽开始时触发。
droppable 元素定义了 ondragover 和 ondrop 事件处理程序,它们用于处理拖放区域的事件。ondragover 阻止默认行为,以允许元素可以放置在该区域,而 ondrop 处理实际的拖放操作,将拖拽的元素追加到目标元素中。
在学习时看到其他值得一看的文章,把 HTML 拖放 API描述的很详细
相关文章:
js实现拖拽功能
基于onMouseDown 、onMouseMove 、onMouseUp 使用 mousedown、mousemove 和 mouseup 事件来实现拖拽的基本思路是: 在 mousedown 事件中,开始追踪拖拽操作并记录鼠标按下的位置。 在 mousemove 事件中,根据鼠标的移动,更新被拖拽…...
数据库主从切换过程中Druid没法获取连接错误
背景: 今天dba在进行DB的主从切换,导致应用一直报错,获取不到DB连接,druid的错误信息如下: Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.GetConnectionTimeoutExc…...
【iOS】Mac M1安装iPhone及iPad的app时设置问题
【iOS】Mac M1安装iPhone及iPad的app时设置问题 简介一,设置问题二,适配问题 简介 由于 苹果M1芯片的Mac可用安装iPhone以及iPad应用,因为开发者并没有适配Mac,因此产生了很多奇怪问题,这里总结归纳Mac M1安装iPhone和…...
Springboot 启动报错@spring.active@解析错误
Caused by: org.yaml.snakeyaml.scanner.ScannerException: while scanning for the next token found character that cannot start any token. (Do not use for indentation)in reader, line 10, column 13:active: spring.active^查看是否勾选...
【算法挨揍日记】day15——560. 和为 K 的子数组、974. 和可被 K 整除的子数组
560. 和为 K 的子数组 560. 和为 K 的子数组 题目描述: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。 子数组是数组中元素的连续非空序列。 解题思路: 我们可以很容易想到暴力解法…...
数字时代的探索与革新:Socks5代理的引领作用
在当今快速发展的数字时代,技术创新推动着社会的变革与进步。Socks5代理作为一项重要的网络技术,正引领着跨界电商、爬虫数据分析、企业全球化和游戏体验优化等领域的发展。本文将深入探讨Socks5代理技术在这些领域中的引领作用,以及它如何塑…...
算法-堆/归并排序-排序链表
算法-堆/归并排序-排序链表 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/sort-list/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 优先级队列构建大顶堆 2.1 思路 优先级队列构建小顶堆链表所有元素放入小顶堆依次取出堆顶…...
word 如何编写4x4矩阵
百度上给的教程,打印出来没有对齐 https://jingyan.baidu.com/article/6b182309995f8dba58e159fc.html 百度上的方式试了一下,不会对齐。导致公式看起来很奇怪。 下面方式会自动对齐 摸索了一下发现可以用下面这种方式编写 4x4 矩阵。先创建一个 3x3…...
INTELlij IDEA编辑VUE项目
菜单中选择setting–>Plugins 或者快捷键 ctrlalts 搜索vue,但有些情况会搜索不出来,先说搜索到的情况 如下图所示: 如果没有vue.js则说明过去已经安装了。 搜索到了后点击Install安装即可, 但即使搜索成功了,也不…...
linux进程间通讯--信号量
1.认识信号量 方便理解:信号量就是一个计数器。当它大于0能用,小于等于0,用不了,这个值自己给。 2.特点: 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。信号量基于操作系统的 PV 操作&am…...
VS Code连接远程Linux服务器开发c++项目
1.在远程 Linux 上安装包 yum groupinstall "development tools" -y yum install cmake -y2.在 VSCode 上安装插件 C/CC/C Extension PackCMakeCMake ToolsCMake Language Support 3.连接远程Linux服务器...
stable diffusion的模型选择,采样器选择,关键词
一、Stable Diffusion的模型选择: 模型下载地址:https://civitai.com/,需要科学上网。 Deliberate:全能模型,prompt越详细生成的图片质量越好Realistic Vision:现实模型,生成仿真式图片&#…...
BI零售数据分析:以自身视角展开分析
随着零售业务不断扩展,市场竞争不断加剧,各层级的销售管理人员都急需一张能快速查看销售数据分析报表,能从中知道自己管辖内的业务最近或过去的情况,并依次为依据科学优化销售管理措施。这就要求零售数据分析报表信息足够多、数据…...
Maven 使用教程(三)
一、如何使用外部依赖项? 您可能已经注意到POM中的一个dependencies元素,我们一直在使用它作为示例。事实上,您一直在使用外部依赖项,但在这里我们将更详细地讨论它是如何工作的。有关更全面的介绍,请参阅我们的依赖机…...
行秋找工作的记录
2023-10-17 15:35-16:00 中移(苏州)研发中心面试 问了项目,还有一些我没准备到的Java八股文:Java类的加载过程,发射机制,redis存储结构,二叉平衡树等。但我也都没回答上来。应该无了。 2023-1…...
vue项目打包,使用externals抽离公共的第三方库
封装了一个插件,用来vue打包抽离公共的第三方库,使用unplugin进行插件开发,vite对应的功能使用了vite-plugin-externals进行二次开发 github地址 npm地址 hfex-auto-externals-plugin 自动注入插件,使用 unplugin 和 html-webpack-plugin进…...
九阳真经之各大厂校招
大学计算机系的同学要怎么努力才能校招进大厂? 秋招的大公司非常多,也是非常好的,赶上了秋招,你基本工作就敲定了,在整个应届毕业生的人群中你就占据很大的优势了。 如何准备应届校招? 一、做好规划,把…...
Go语言入门心法(五): 函数
Go语言入门心法(一): 基础语法 Go语言入门心法(二): 结构体 Go语言入门心法(三): 接口 Go语言入门心法(四): 异常体系 Go语言入门心法(五): 函数 一: go语言函数认知 函数相关认知升维:函数的功能就是把相对独立的某个相同或者时类型的功能抽象处理,使之成为一个…...
gitignore文件的语法规则
行注释:以"#"符号开头的行表示注释,Git会忽略这些行。空行:空行会被忽略。文件和目录规则: 可以使用通配符来匹配文件和目录。常用的通配符有: “*”:匹配0个或多个字符。“?”:匹配…...
vscode提示扩展主机在过去5分钟内意外终止了3次,解决方法
参考链接: https://code.visualstudio.com/blogs/2021/02/16/extension-bisect https://code.visualstudio.com/docs/setup/uninstall#_clean-uninstall 使用vscode打开jupyter notebook记事本时,窗口右下角提示扩展主机在过去5分钟内意外终止了3次 而…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
