JS的拖拽案例

630 阅读1分钟
<!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>Document</title>
<style>
* {
  padding: 0;
  margin: 0;
}
div {
  background-color: pink;
  width: 100px;
  height: 100px;
  position: absolute;
}
</style>
</head>
<body>
<div></div>
<script>
/**
 * 拖拽效果
 * 
 *    问题1:事件类型是什么?(拖拽3要素)
 *        => 鼠标按下
 *        => 鼠标移动
 *        => 鼠标抬起
 *    问题2:对应事件类型 的 事件源是什么?
 *        => 鼠标按下
 *                => div
 *        => 鼠标移动
 *                => 当前文档/div(有瑕疵)
 *        => 鼠标抬起
 *                => div
 *    问题3:移动距离是多少?
 *        不是说单纯的鼠标移动到某一个坐标点,就代表移动多少
 *        解决:
 *            1。在鼠标按下的时候,记录元素本身的坐标
 *            2。在鼠标移动的时候,重新获取最新的坐标
 *            var 移动距离 = 最新的坐标 - 最初的坐标
 *    问题4:是直接将移动距离赋值给元素吗?
 *        1.在鼠标按下的时候,记录元素本身的偏移量
 *        2.将本身的偏移量与移动距离相加
 *        3.将相加的和,赋值给元素
 * */ 
// 0.获取元素
var oDiv = document.querySelector('div')
// 0.准备全局变量
var flag = false //用于控制鼠标移动事件是否执行
var startX = 0 //记录鼠标在按下时X轴的位置
var startY = 0 //记录鼠标在按下时Y轴的位置
var eleTop = 0 //记录鼠标在按下时 元素本身距离顶部的偏移量
var eleLeft = 0 //记录鼠标在按下时 元素本身距离左侧的偏移量

// 1.鼠标按下
oDiv.onmousedown = function(e) {
  // console.log('鼠标按下事件触发')
  flag = true
  // 1.1 记录鼠标的坐标
  startX = e.clientX
  startY = e.clientY
  // 1.2记录元素本身的偏移量
  eleTop = oDiv.offsetTop
  eleLeft = oDiv.offsetLeft
}
// 2.鼠标移动
document.onmousemove = function(e) {
  if(flag === false) return
  // console.log('鼠标移动事件触发')
  // console.log(startX, startY)
  // console.log(eleTop, eleLeft)
  // 2.1获取最新坐标
  var newX = e.clientX
  var newY = e.clientY
  // 2.2计算移动距离 === 最新坐标 - 最初坐标
  var moveX = newX - startX
  var moveY = newY - startY
  // 2.3将本身的偏移量与移动距离相加
  var x = eleLeft + moveX
  var y = eleTop + moveY
  // 2.4将相加的和,赋值给元素
  oDiv.style.left = x + 'px'
  oDiv.style.top = y + 'px'
}
// 3.鼠标抬起
oDiv.onmouseup = function() {
  // console.log('鼠标抬起事件触发')
  flag = false
}

/**
 * 开关变量的逻辑:
 *      1. 打开页面首次进入
 *          flag === false    然后鼠标移动事件 内部if条件成立 直接return不会执行函数内部代码
 *      2.鼠标按下事件触发,将fLag的值修改为true
 *          fLag=-=true   然后鼠标移动事件内部if条件不成立,开始正常执行函数内部代码
 *      3.鼠标抬起事件触发,将fLag的值修改为false
 *          fLag === false   然后鼠标移动时间内部i计条件成立。直接return 不会执行函数内部代码
 * */