惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Privacy International News Feed
V
Vulnerabilities – Threatpost
The Last Watchdog
The Last Watchdog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
O
OpenAI News
T
Threat Research - Cisco Blogs
WordPress大学
WordPress大学
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Palo Alto Networks Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Help Net Security
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
T
The Blog of Author Tim Ferriss
H
Hackread – Cybersecurity News, Data Breaches, AI and More
S
Securelist
Vercel News
Vercel News
S
Security Affairs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
B
Blog RSS Feed
云风的 BLOG
云风的 BLOG
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Blog — PlanetScale
Blog — PlanetScale
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Last Week in AI
Last Week in AI
博客园_首页
Attack and Defense Labs
Attack and Defense Labs
G
Google Developers Blog
T
Tor Project blog
Project Zero
Project Zero
腾讯CDC
Schneier on Security
Schneier on Security
月光博客
月光博客
N
Netflix TechBlog - Medium
AWS News Blog
AWS News Blog
L
LINUX DO - 最新话题
P
Proofpoint News Feed
博客园 - 司徒正美
A
About on SuperTechFans
Latest news
Latest news
Scott Helme
Scott Helme
Hacker News: Ask HN
Hacker News: Ask HN
T
Threatpost
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
CERT Recently Published Vulnerability Notes
Google DeepMind News
Google DeepMind News
博客园 - 聂微东

梦魇小栈

《羊了个羊》程序员过关攻略 WebRTC 入门指南 将你的博客升级为 PWA 渐进式Web离线应用 什么? 微信没有年度账单? 前端 nodejs 撸起来~ [接口实现] Hexo 博客美化代码块 记一下 pm2 常用配置及命令 (译)NPM vs Yarn 备忘手册 用 MySQL 导入 SQL 文件 解决 ubuntu 服务器中文乱码 面试分享:2018阿里巴巴前端面试总结(题目+答案) crontab 踩坑之绝对路径 SED 命令简明教程 在Hexo博客 NexT主题中部署Wildfire评论系统 Merry Christmas JAVASCRIPT生成图形验证码 笔记:NPM版本号自增,自动化发布NPM包 不可不知的Mac OS X专用命令行工具(持续更新中) 继多说、网易关停之后该何去何从(网易云跟帖宣布2017年8月1日停止服务) 重新介绍 JavaScript(JS全面系列教程)
使用 JavaScript 实现简单的拖拽
Ihoey 心,若没有栖息的地方,到哪里都是流浪...... · 2018-01-29 · via 梦魇小栈

发表于 | 更新于 | 分类于 javascript | 评论数: | 阅读次数:

步骤

使用 JavaScript 实现拖拽的步骤:

  • 让元素捕获事件(mousedown, mousemove & mouseup
  • 单击并不释放,触发 mousedown,标记开始拖拽,并获取元素和鼠标的位置
  • 拖动鼠标,触发 mousemove,不断的获取鼠标的位置,并通过计算重新确定元素的位置
  • 释放师表,触发 mouseup,结束拖拽,确定元素位置并更新

被拖拽的元素必须是相对父元素定位,或者是绝对定位

实现

绑定事件

首先,对拖拽的元素绑定 mousedown 时间,使其触发对应的函数,获取元素与鼠标的位置。在 document 对象上绑定 mousemovemouseup 事件,不在拖拽的元素上绑定是因为当鼠标移动太快而超出元素的范围时会停止拖拽,而绑定在 document 上则可以避免这样的事情发生。拖拽再快都不会超出 document 的范围。

绑定事件:

1
2
3
4
5
var box = document.getElementById('box');

box.onmousedown = down;
document.onmousemove = move;
document.onmouseup = up;

获取鼠标位置

鼠标位置可以在 event 对象中获得,常用的属性有:

  • clientX / clientY : 相对浏览器窗口坐标
  • offsetX / offsetY : 相对事件目标对象坐标
  • pageX / pageY : 相对 document 对象坐标

一般鼠标的位置使用 pageX / pageY 获取,但是 IE 不支持这两个属性。所以在 IE 中使用 event.clientX + document.body.scrollLeft - document.body.clientLeft; 获取鼠标的位置。

获取鼠标位置的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function getMouseXY(e) {
var x = 0, y = 0;
e = e || window.event;
if (e.pageX) {
x = e.pageX;
y = e.pageY;
} else {
x = e.clientX + document.body.scrollLeft - document.body.clientLeft;
y = e.clientY + document.body.scrollTop - document.body.clientTop;
}
return {
x: x,
y: y
};
}

事件触发函数

mousedown
当鼠标移动到元素内并点击元素不放时,触发 mousedown 事件。按照上面的步骤,这一步是获取元素与鼠标的位置,用于触发 mousemove 时计算元素的位置。

mousedown 触发的函数:

1
2
3
4
5
6
7
8
9
function down(e) {
dragging = true;
boxX = box.offsetLeft;
boxY = box.offsetTop;
mouseX = parseInt(getMouseXY(e).x);
mouseY = parseInt(getMouseXY(e).y);
offsetX = mouseX - boxX;
offsetY = mouseY - boxY;
}

boxX / boxY 为元素左上角相对于已定位的父元素(相对或者绝对定位的父元素)的偏移的像素值,即元素左上角的坐标。
mouseX / mouseY 是通过 getMouseXY 函数获得的鼠标的坐标。
offsetX/ offsetY 是鼠标相对于元素坐标(左上角坐标)的坐标。
mousemove
当鼠标移动时,不断的获取鼠标的位置,并计算元素的新坐标修改元素的位置样式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function move(e) {
if (dragging) {
var x = getMouseXY(e).x - offsetX;
var y = getMouseXY(e).y - offsetY;
var width = document.documentElement.clientWidth - box.offsetWidth;
var height = document.documentElement.clientHeight - box.offsetHeight;

x = Math.min(Math.max(0, x), width);
y = Math.min(Math.max(0, y), height);

box.style.left = x + 'px';
box.style.top = y + 'px';
}
}

变量 width / height 表示可移动的位置的大小,这里是 document 减去元素的大小(元素不会超出可移动的范围)。
Math.min 使得元素不会超出可移动访问的右边界(元素 x 坐标不会超过 width),Math.max 使得元素不会超出可移动范围的左边界(元素的 x 坐标不小于 0)。
最后将改变后的元素 lefttop 值应用当元素上,即修改元素的样式。
mouseup
拖拽结束,取消拖拽的标记。使其触发 mousemove 事件,但不做任何处理。

1
2
3
function up(e) {
dragging = false;
}

在线演示

总结

上面使用的简单的 JavaScript 代码实现了元素的拖拽,但并没有对兼容性问题全面考虑,也没有对性能优化,有不必要的事件触发。

满分是10分的话,这篇文章你给几分,您的支持将鼓励我继续创作!