1.1-拖拽盒子 - 基本流程
思路分析
本小节知识点:鼠标拖拽
- 复习鼠标事件:
- onclick:鼠标点下去并且弹起来触发(单击一次)
- ondblclick:鼠标连续点击两次(双击)
- onmousedown:鼠标按下就触发
- onmouseup: 鼠标弹起触发
- onmouseover:鼠标移入
- onmouseout:鼠标移出
- onmousemove:鼠标移动
- 鼠标拖拽:(1)先按下 (2)然后移动 (3)最后松开
<!DOCTYPE html>
<html lang="zh-CN">
<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>盒子拖拽 - 基本流程</title>
<style>
.box {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
// 盒子拖拽: 三步骤
const box = document.querySelector('.box')
// 1. 鼠标按下: 记录鼠标相对位置
box.onmousedown = function (e) {
// console.log(e)
// 减去原来位置的目的: 为了能够二次拖拽(如果只有一次性拖拽: 可以不用减去原有的偏移)
let x = e.pageX - parseInt(getComputedStyle(box).left)
let y = e.pageY - parseInt(getComputedStyle(box).top)
console.log(x, y)
// 上述代码不够优化: getComputedStyle(box)获取box的全部样式, 占用资源很多, 所以应该定义一个变量运行一次函数getComputedStyle()
// 2. 鼠标移动: 一定在鼠标按下的事件内部, 移动盒子
// 移动代表的是移动范围: 给移动范围对象增加移动事件
document.onmousemove = function (e) {
// 移动范围: 整个页面
box.style.left = e.pageX - x + 'px'
box.style.top = e.pageY - y + 'px'
}
// 3. 鼠标松开: 一定在鼠标按下的事件内容
// 给谁加的按下事件,给谁加松开事件
box.onmouseup = function () {
// 释放document的移动事件
document.onmousemove = null
}
}
</script>
</body>
</html>
1.2-拖拽盒子02(元素有margin)
<!DOCTYPE html>
<html lang="zh-CN">
<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>盒子拖拽 - 带margin</title>
<style>
.box {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 200px;
background-color: red;
margin-left: 50px;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
// 盒子拖拽: 三步骤
const box = document.querySelector('.box')
// 1. 鼠标按下: 记录鼠标相对位置
box.onmousedown = function (e) {
// console.log(e)
// 减去原来位置的目的: 为了能够二次拖拽(如果只有一次性拖拽: 可以不用减去原有的偏移)
let x = e.pageX - parseInt(getComputedStyle(box).left)
let y = e.pageY - parseInt(getComputedStyle(box).top)
// 如果被拖拽的盒子有margin: 不要使用offset系列(自动带margin)
// let x = e.pageX - box.offsetLeft
// let y = e.pageY - box.offsetTop
console.log(x, y)
// 上述代码不够优化: getComputedStyle(box)获取box的全部样式, 占用资源很多, 所以应该定义一个变量运行一次函数getComputedStyle()
// 2. 鼠标移动: 一定在鼠标按下的事件内部, 移动盒子
// 移动代表的是移动范围: 给移动范围对象增加移动事件
document.onmousemove = function (e) {
// 移动范围: 整个页面
box.style.left = e.pageX - x + 'px'
box.style.top = e.pageY - y + 'px'
}
// 3. 鼠标松开: 一定在鼠标按下的事件内容
// 给谁加的按下事件,给谁加松开事件
box.onmouseup = function () {
// 释放document的移动事件
document.onmousemove = null
}
}
// 但凡有盒子拖拽: 不用使用offset来获取偏移,用getComuptedStyle()获取真实的定位偏移
</script>
</body>
</html>
1.3-案例:拖拽登录验证
<!DOCTYPE html>
<html lang="zh-CN">
<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>盒子拖拽 - 登陆验证</title>
<style>
.wrap {
width: 360px;
height: 180px;
margin: 50px auto;
border: 1px solid black;
position: relative;
}
.wrap .icon {
position: absolute;
left: 0;
top: 60px;
}
.wrap .progress {
width: 100%;
height: 40px;
position: relative;
top: -4px;
background-color: pink;
}
.cube {
position: absolute;
width: 40px;
height: 40px;
background-color: red;
cursor: pointer;
}
.bar {
position: absolute;
width: 0px;
height: 40px;
background-color: green;
}
</style>
</head>
<body>
<div class="wrap">
<img src="./images/drag01.png" alt="">
<img class="icon" src="./images/drag02.png" alt="">
<div class="progress">
<div class="bar"></div>
<div class="cube"></div>
</div>
</div>
<script>
// 需求: 拖拽登录验证
// 细节1: 如果拖拽没有到达目标 或者 超出目标: 登录失败(刷新页面)
// 细节2: 拖动多少代表成功呢?
// 拖拽三步走
const wrap = document.querySelector('.wrap')
const icon = document.querySelector('.wrap .icon')
const bar = document.querySelector('.wrap .bar')
const cube = document.querySelector('.wrap .cube')
// 1. 鼠标按下: 几下鼠标当前位置
cube.onmousedown = function (e) {
let x = e.pageX
// 2. 鼠标移动: 在整个框中拖动, 给框添加鼠标移动事件
// 考虑安全: 不能小于0, 也不能大于框的宽度
let distance = 0
wrap.onmousemove = function (e) {
distance = e.pageX - x
// 安全
if (distance < 0) distance = 0
if (distance > wrap.offsetWidth - cube.offsetWidth) distance = wrap.offsetWidth - cube.offsetWidth
icon.style.left = distance + 'px'
bar.style.width = distance + 'px'
cube.style.left = distance + 'px'
console.log(distance)
}
// 3. 鼠标松开: 干掉移动事件, 判定拖动的距离是否满足验证条件
cube.onmouseup = function () {
wrap.onmousemove = null
// 判定移动了多少
if (distance >= 150 && distance <= 160) {
alert('验证成功,正在跳转')
location.assign('http://www.itcast.cn')
} else {
alert('验证失败,请再次验证')
location.reload()
}
}
}
// 总结
// 一次性拖拽: 不要算相对位置, 终点位置 - 起始位置 即可
// mousemove里面的变量在mouseup中不能用: 要用,要提升变量
</script>
</body>
</html>```