curTain

拖拽 DOM 碰撞检测

分析:

总共分为两步:

  1. 实现拖拽
  2. 碰撞检测

实现拖拽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let red = document.getElementsByClassName("red")[0];

red.addEventListener( "mousedown", (event) => {
// 事先记录下与元素左上角的偏移
let left = event.clientX - red.offsetLeft;
let top = event.clientY - red.offsetTop;
// 使用 addEventListener 方式添加事件监听,后期不好移除,故使用 onmousemove
document.onmousemove = move.bind( this, left, top )
})

// 监听抬起事件
document.addEventListener("mouseup", () => {
document.onmousemove = ""
})

function move( left, top ){
let event = Array.from(arguments)[2];
// 先固定左上角的偏移量 - 偏移量,让元素跟随鼠标移动
red.style.left = event.clientX - left + "px";
red.style.top = event.clientY - top + "px";
}

DOM 碰撞检测

  1. 当div1在div2的上边线(t2)以上的区域活动时,始终碰不上
  2. 当div1在div2的右边线(r2)以右的区域活动时,始终碰不上
  3. 当div1在div2的下边线(b2)以下的区域活动时,始终碰不上
  4. 当div1在div2的左边线(r2)以左的区域活动时,始终碰不上

除了以上四种情况,其他情况表示div1和div2碰上了,下面试完整测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="red"></div>
<div class="green"></div>
<style>
div {
width: 100px;
height: 100px;
}
.red {
position: absolute;
background-color: red;
}
.green{
background-color: green;
position: relative;
top: 300px;
left: 300px;
}
.blue {
background-color: blue;
}
</style>
<script>
/**
* 题目描述:在页面中写一个红色正方形,实现红色正方形拖拽到页面的任意位置,随鼠标一起动,
* 页面中有另一个绿色正方形,当鼠标拖动红色正方形移动到绿色正方形时,绿色正方形变蓝色
*
* 实现思路:1.实现随鼠标拖拽,2.拖拽的过程中判定是否碰撞
*/

let red = document.getElementsByClassName("red")[0];
let green = document.getElementsByClassName("green")[0];

function move( left, top ){
let event = Array.from(arguments)[2];
// 先固定左上角的偏移量 - 偏移量,让元素跟随鼠标移动
red.style.left = event.clientX - left + "px";
red.style.top = event.clientY - top + "px";

// 获取目标元素四个边框的偏移
let greenleft = green.offsetLeft
let greenTop = green.offsetTop
let greenRight = green.offsetLeft + green.offsetWidth
let greenbottom = green.offsetTop + green.offsetHeight

// 拖拽元素的左边框偏移 大于 目标元素的右边框偏移
// 拖拽元素的顶部边框偏移 大于 目标元素的底部偏移
// 拖拽元素的右边框偏移 小于 目标元素的左边框偏移
// 拖拽元素的底部边框偏移 大于 目标元素的顶部边框偏移
// 其中一个成立,就代表没有碰撞,反之则表示已经碰撞
if( red.offsetLeft > greenRight ||
red.offsetTop > greenbottom||
red.offsetLeft + red.offsetWidth < greenleft ||
red.offsetTop + red.offsetHeight < greenTop){
// 移除 css 类
green.classList.remove("blue")
} else {
green.classList.add("blue")
}
}

red.addEventListener( "mousedown", (event) => {
// 事先记录下与元素左上角的偏移
let left = event.clientX - red.offsetLeft;
let top = event.clientY - red.offsetTop;
// 使用 addEventListener 方式添加事件监听,后期不好移除,故使用 onmousemove
document.onmousemove = move.bind( this, left, top )
})

// 监听抬起事件
document.addEventListener("mouseup", () => {
document.onmousemove = ""
})

</script>
</body>
</html>

参考材料

JS实现碰撞检测的方法分析


 评论