拖拽事件是很常见的dom操作,但是实现起来却经常让人感到一头雾水,不熟悉dom事件和盒模型的新人可能更是感觉无从下手,那么接下来就从最基本的概念来学习如何实现一个拖拽操作。
把大象装进冰箱需要几步
答案大家或许都知道:
- 打开冰箱门
- 把大象塞进冰箱
- 关上冰箱门
这个问题可能看上去像是个笑话或者脑筋急转弯,但是我想说的是,这个问题的分析逻辑值得去借鉴:也就是把一个复杂的流程按执行顺序拆解成若干个相对简单并且可执行的子步骤,完成每个子步骤,最终实现一个完整的流程。
那么我们不妨思考一下,一次拖拽可以分为几个步骤?
我们不妨这么拆解:
1.按下鼠标
2.拖动元素
3.松开鼠标
是不是跟上面把大象关进冰箱的问题很像?我们把拖拽事件分成三个步骤,接下来我们只需要思考每一步具体怎么执行。
(PS:从一个更专业的角度,我可能会这样描述这个过程:
1.鼠标按下,元素跟随光标移动
2.鼠标抬起元素停止移动
3.移动的区域进行限制(只能在屏幕可视区域内移动-不产生滚动条)
4.鼠标抬起之后,移除移动和抬起事件)
准备知识
2.1 处理拖拽的事件:
mousedown
:在鼠标按下某个元素时触发。当用户按下鼠标左键、中键或右键时,该事件被触发。通常用于捕捉鼠标点击的起始点。
mousemove
:在鼠标在某个元素上移动时触发。当用户在元素上移动鼠标时,该事件会连续触发。可以使用该事件来实现鼠标跟随、拖拽等交互效果。
mouseup
:在鼠标释放某个元素时触发。当用户释放鼠标按键时,该事件被触发。通常用于捕捉鼠标点击的结束点。
2.2 事件的坐标:
clientX
和clientY
属性表示鼠标相对于浏览器窗口(viewport)的水平和垂直坐标,这两个属性的值是相对于浏览器窗口的左上角而言的。offsetX
和offsetY
属性表示鼠标相对于触发事件的元素的水平和垂直坐标,这两个属性的值是相对于元素自身而言的。
动手实践!
3.1鼠标按下元素跟随光标移动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0px;
margin: 0px;
}
.content {
width: 300px;
height: 300px;
background: pink;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="content" id="moveElement">我可以移动</div>
<script>
window.onload = function() {
// 获取元素节点
let el = document.getElementById('moveElement');
// 用于记录鼠标按下去的那一个点距离边框顶部和左侧的距离
let offsetX = null
let offsetY = null
// 给元素注册鼠标按下事件
el.onmousedown = function(e) {
//兼容 e || window.event 现在都可以
let event = e || window.event;
console.log(event)
offsetX = event.offsetX;
offsetY = event.offsetY;
// 鼠标移动(小方块在文档上移动,给文档注册一个移动事件)
document.onmousemove = function(event) {
let e = event || window.event;
// 获取鼠标移动的坐标位置
let left = e.clientX - offsetX;
let top = e.clientY - offsetY;
// 将移动的新的坐标位置进行赋值
el.style.left = left + 'px';
el.styl