javascript动画系列第三篇——碰撞检测
前面的话
前面分别介绍了拖拽模拟和磁性吸附,当可视区域内存在多个可拖拽元素,就出现碰撞检测的问题,这也是javascript动画的一个经典问题。本篇将详细介绍碰撞检测
原理介绍
碰撞检测的方法有很多,接下来使用九宫格分析法
假设黄色元素要与红色元素进行碰撞。将红色元素所处的区域分为9部分,自身处于第9部分,周围还存在8个部分。只要黄色元素进入红色元素的第9部分,就算碰撞。否则,都算未碰撞

总共分为以下5种情况:
1、处于上侧未碰撞区域——1、2、3区域
2、处于右侧未碰撞区域——3、4、5区域
3、处于下侧未碰撞区域——5、6、7区域
4、处于左侧未碰撞区域——1、7、8区域
5、处于碰撞区域——9区域
代码实现
我们把上面的原理用代码实现
function bump(obj,objOther,bgColor){
/***被碰元素***/
//被碰元素左侧距离可视区域左侧的距离
var L0 = obj.offsetLeft;
//被碰元素上侧距离可视区域上侧的距离
var T0 = obj.offsetTop;
//被碰元素右侧距离可视区域右侧的距离
var R0 = obj.offsetLeft + obj.offsetWidth;
//被碰元素下侧距离可视区域下侧的距离
var B0 = obj.offsetTop + obj.offsetHeight;
/**侵入元素**/
var L = objOther.offsetLeft;
var T = objOther.offsetTop;
var R = objOther.offsetLeft + objOther.offsetWidth;
var B = objOther.offsetTop + objOther.offsetHeight;
/*******碰撞检测*******/
//上侧区域if(B < T0)
//左侧区域if(R < L0)
//右侧区域if(L > R0)
//下侧区域if(T > B0)
//碰撞区域
if(B >= T0 && R >= L0 && L <= R0 && T <= B0){
obj.style.backgroundColor = 'red';
}else{
obj.style.backgroundColor = bgColor;
}
} 完整效果
<div id="test1" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;">元素一</div>
<div id="test2" style="height: 100px;width: 100px;background:orange;position:absolute;top:150px;left:150px;">元素二</div>
<script>
function bump(obj,objOther,bgColor){
/***被碰元素***/
//被碰元素左侧距离可视区域左侧的距离
var L0 = obj.offsetLeft;
//被碰元素上侧距离可视区域上侧的距离
var T0 = obj.offsetTop;
//被碰元素右侧距离可视区域右侧的距离
var R0 = obj.offsetLeft + obj.offsetWidth;
//被碰元素下侧距离可视区域下侧的距离
var B0 = obj.offsetTop + obj.offsetHeight;
/**侵入元素**/
var L = objOther.offsetLeft;
var T = objOther.offsetTop;
var R = objOther.offsetLeft + objOther.offsetWidth;
var B = objOther.offsetTop + objOther.offsetHeight;
/*******碰撞检测*******/
//上侧区域if(B < T0)
//左侧区域if(R < L0)
//右侧区域if(L > R0)
//下侧区域if(T > B0)
//碰撞区域
if(B >= T0 && R >= L0 && L <= R0 && T <= B0){
obj.style.backgroundColor = 'red';
}else{
obj.style.backgroundColor = bgColor;
}
}
function drag(obj){
obj.onmousedown = function(e){
e = e || event;
//提升当前元素的层级
obj.style.zIndex = '1';
//获取元素距离定位父级的x轴及y轴距离
var x0 = this.offsetLeft;
var y0 = this.offsetTop;
//获取此时鼠标距离视口左上角的x轴及y轴距离
var x1 = e.clientX;
var y1 = e.clientY;
//鼠标按下时,获得此时的页面区域
var L0 = 0;
var R0 = document.documentElement.clientWidth;
var T0 = 0;
var B0 = document.documentElement.clientHeight;
//鼠标按下时,获得此时的元素宽高
var EH = obj.offsetHeight;
var EW = obj.offsetWidth;
document.onmousemove = function(e){
e = e || event;
//获取此时鼠标距离视口左上角的x轴及y轴距离
x2 = e.clientX;
y2 = e.clientY;
//计算此时元素应该距离视口左上角的x轴及y轴距离
var X = x0 + (x2 - x1);
var Y = y0 + (y2 - y1);
/******范围限定*******/
//获取鼠标移动时元素四边的瞬时值
var L = X;
var R = X + EW;
var T = Y;
var B = Y + EH;
//在将X和Y赋值给left和top之前,进行范围限定
//只有在范围内时,才进行相应的移动
//如果脱离左侧范围,则left置L0
if(L < L0){X = L0;}
//如果脱离右侧范围,则left置为R0
if(R > R0){X = R0 - EW;}
//如果脱离上侧范围,则top置T0
if(T < T0){Y = T0;}
//如果脱离下侧范围,则top置为B0
if(B > B0){Y = B0 - EH;}
obj.style.left = X + 'px';
obj.style.top = Y + 'px';
//运行碰撞检测函数
bump(test2,test1,'orange')
}
document.onmouseup = function(e){
//降低当前元素的层级
obj.style.zIndex = '0';
//当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可
document.onmousemove = null;
//释放全局捕获
if(obj.releaseCapture){
obj.releaseCapture();
}
}
//阻止默认行为
return false;
//IE8-浏览器阻止默认行为
if(obj.setCapture){
obj.setCapture();
}
}
}
drag(test1);
drag(test2);
</script> 源码查看
相关推荐
zrtlin 2020-11-09
wikiwater 2020-10-27
heheeheh 2020-10-19
Crazyshark 2020-09-15
ZGCdemo 2020-08-16
jczwilliam 2020-08-16
littleFatty 2020-08-16
idning 2020-08-03
jinxiutong 2020-07-26
lanzhusiyu 2020-07-19
Skyline 2020-07-04
xiaofanguan 2020-06-25
Aveiox 2020-06-23
dragonzht 2020-06-17