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){
/***被碰元素***/<br/>
//被碰元素左侧距离可视区域左侧的距离<br/>
var L0 = obj.offsetLeft;<br/>
//被碰元素上侧距离可视区域上侧的距离<br/>
var T0 = obj.offsetTop;<br/>
//被碰元素右侧距离可视区域右侧的距离<br/>
var R0 = obj.offsetLeft + obj.offsetWidth;<br/>
//被碰元素下侧距离可视区域下侧的距离<br/>
var B0 = obj.offsetTop + obj.offsetHeight;<br/>
/**侵入元素**/<br/>
var L = objOther.offsetLeft;<br/>
var T = objOther.offsetTop;<br/>
var R = objOther.offsetLeft + objOther.offsetWidth;<br/>
var B = objOther.offsetTop + objOther.offsetHeight;
/*******碰撞检测*******/<br/>
//上侧区域if(B < T0)<br/>
//左侧区域if(R < L0)<br/>
//右侧区域if(L > R0)<br/>
//下侧区域if(T > B0)
//碰撞区域<br/>
if(B >= T0 && R >= L0 && L <= R0 && T <= B0){<br/>
obj.style.backgroundColor = 'red';<br/>
}else{<br/>
obj.style.backgroundColor = bgColor;<br/>
}<br/>
}
完整效果
<div id="test1" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;">元素一</div><br/>
<div id="test2" style="height: 100px;width: 100px;background:orange;position:absolute;top:150px;left:150px;">元素二</div><br/>
<script><br/>
function addEvent(target,type,handler){<br/>
if(target.addEventListener){<br/>
target.addEventListener(type,handler,false);<br/>
}else{<br/>
target.attachEvent('on'+type,function(event){<br/>
return handler.call(target,event);<br/>
});<br/>
}<br/>
}<br/>
function getCSS(obj,style){<br/>
if(window.getComputedStyle){<br/>
return getComputedStyle(obj)[style];<br/>
}<br/>
return obj.currentStyle[style];<br/>
}<br/>
function bump(obj,objOther){<br/>
bump.objBGColor = (bump.objBGColor === undefined) ? getCSS(obj,'backgroundColor') : bump.objBGColor;<br/>
bump.objOtherBGColor = (bump.objOtherBGColor === undefined) ? getCSS(objOther,'backgroundColor') : bump.objOtherBGColor;<br/>
/***被碰元素***/<br/>
//被碰元素左侧距离可视区域左侧的距离<br/>
var L0 = obj.offsetLeft;<br/>
//被碰元素上侧距离可视区域上侧的距离<br/>
var T0 = obj.offsetTop;<br/>
//被碰元素右侧距离可视区域右侧的距离<br/>
var R0 = obj.offsetLeft + obj.offsetWidth;<br/>
//被碰元素下侧距离可视区域下侧的距离<br/>
var B0 = obj.offsetTop + obj.offsetHeight;<br/>
/**侵入元素**/<br/>
var L = objOther.offsetLeft;<br/>
var T = objOther.offsetTop;<br/>
var R = objOther.offsetLeft + objOther.offsetWidth;<br/>
var B = objOther.offsetTop + objOther.offsetHeight;
/*******碰撞检测*******/<br/>
//上侧区域if(B < T0)<br/>
//左侧区域if(R < L0)<br/>
//右侧区域if(L > R0)<br/>
//下侧区域if(T > B0)
//碰撞区域<br/>
if(B >= T0 && R >= L0 && L <= R0 && T <= B0){<br/>
obj.style.backgroundColor = objOther.style.backgroundColor ='red';<br/>
}else{<br/>
obj.style.backgroundColor = bump.objBGColor;<br/>
objOther.style.backgroundColor = bump.objOtherBGColor;
}<br/>
}
function drag(ele){<br/>
var x0,y0,x1,y1,isMoving;<br/>
var L0,R0,T0,B0,EH,EW;
var mousedownHandler = function(e){<br/>
e = e || event;<br/>
//获取元素距离定位父级的x轴及y轴距离<br/>
x0 = this.offsetLeft;<br/>
y0 = this.offsetTop;<br/>
//获取此时鼠标距离视口左上角的x轴及y轴距离<br/>
x1 = e.clientX;<br/>
y1 = e.clientY;<br/>
//按下鼠标时,表示正在运动<br/>
isMoving = true;<br/>
//鼠标按下时,获得此时的页面区域<br/>
L0 = 0;<br/>
R0 = document.documentElement.clientWidth;<br/>
T0 = 0;<br/>
B0 = document.documentElement.clientHeight;<br/>
//鼠标按下时,获得此时的元素宽高<br/>
EH = ele.offsetHeight;<br/>
EW = ele.offsetWidth;<br/>
}<br/>
var mousemoveHandler = function(e){<br/>
//如果没有触发down事件,而直接触发move事件,则函数直接返回<br/>
if(!isMoving){<br/>
return;<br/>
}<br/>
e = e || event;<br/>
//获取此时鼠标距离视口左上角的x轴及y轴距离<br/>
var x2 = e.clientX;<br/>
var y2 = e.clientY;<br/>
//计算此时元素应该距离视口左上角的x轴及y轴距离<br/>
var X = x0 + (x2 - x1);<br/>
var Y = y0 + (y2 - y1);<br/>
/******范围限定*******/<br/>
//获取鼠标移动时元素四边的瞬时值<br/>
var L = X;<br/>
var R = X + EW;<br/>
var T = Y;<br/>
var B = Y + EH;<br/>
//在将X和Y赋值给left和top之前,进行范围限定。只有在范围内时,才进行相应的移动<br/>
//如果脱离左侧范围,则left置L0<br/>
if(L < L0){X = L0;}<br/>
//如果脱离右侧范围,则left置为R0<br/>
if(R > R0){X = R0 - EW;}<br/>
//如果脱离上侧范围,则top置T0<br/>
if(T < T0){Y = T0;}<br/>
//如果脱离下侧范围,则top置为B0<br/>
if(B > B0){Y = B0 - EH;}
//将X和Y的值赋给left和top,使元素移动到相应位置<br/>
ele.style.left = X + 'px';<br/>
ele.style.top = Y + 'px';
bump(test2,test1);<br/>
}<br/>
var mouseupHandler = function(e){<br/>
//鼠标抬起时,表示停止运动<br/>
isMoving = false;<br/>
//释放全局捕获<br/>
if(ele.releaseCapture){<br/>
ele.releaseCapture();<br/>
}<br/>
}<br/>
var preventDefaultHandler = function(e){<br/>
e = e || event;<br/>
if(e.preventDefault){<br/>
e.preventDefault();<br/>
}else{<br/>
e.returnValue = false;<br/>
}<br/>
//IE8-浏览器阻止默认行为<br/>
if(ele.setCapture){<br/>
ele.setCapture();<br/>
}
}<br/>
addEvent(ele,'mousedown',mousedownHandler);<br/>
addEvent(ele,'mousedown',preventDefaultHandler);<br/>
addEvent(document,'mousemove',mousemoveHandler)<br/>
addEvent(document,'mouseup',mouseupHandler)
};
drag(test1);<br/>
drag(test2);<br/>
</script>
转发申明:
本文转自互联网,由小站整理并发布,在于分享相关技术和知识。版权归原作者所有,如有侵权,请联系本站,将在24小时内删除。谢谢
