前 言
MYBG
小编最近在做自己的个人网站,其中就用到了一个小球碰撞检测的功能,想自己写,无奈本人能力不足啊(毕竟还是一个菜鸟)!!就想着找个插件用一下也好,可是找了好久也没有找到一个比较好用的。好在天无绝人之路,在不断的搜搜巡巡过程中,还是发现了一个,用原生js实现小球碰撞检测的方法,下面分享给大家。
注:本文参考“敲代码不爱找bug的妹子”的一篇博客,详解可参考:http://blog.csdn.net/new_codeer/article/details/52386566
参考过后,经过对原文进行了稍微的改动,特别适用于网站的开发。复制过去,稍微改动一下即可。具体的原代码如下:
一、html代码(body部分) |
- <body>
- <!--只需要做一个大div包裹几个小div即可,你想要几个小球碰撞就在内部做几个div即可,这里我们做了6个小球-->
- <div id="main">
- <div></div>
- <div></div>
- <div></div>
- <div></div>
- <div></div>
- <div></div>
- </div>
- </body>
上面body部分这样就算是完成了,下面我们给body中的div做一些小样式。
二、CSS小球样式部分 |
- <style type="text/css">
- /*将body默认的margin和padding部分去掉*/
- *{
- margin: 0px;
- padding: 0px;
- }
- /*采用定位的方式,让小球运动起来*/
- #main{
- margin: 0px auto;
- position: relative;
- }
- /*小球的样式*/
- #main div{
- overflow: hidden;
- position: absolute;
- width: 80px;
- height: 80px;
- opacity: 0.5;
- border-radius: 50%;
- background-color: red;
- }
- </style>
小球是要运动起来的,我们通过给小球和它的父元素添加定位,最后用js改变其top、bottom、left、right值来让小球运动。现在我们小球的样式已经做好了,下面的js代码才是重中之重。
3.1 Android 事件基础知识 |
- <script type="text/javascript">
- var main = document.getElementById("main"); //取到小球父元素
- var circles = main.getElementsByTagName("div"); //取到小球
- var st = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
- var json = [],
- arr = [],
- color = [];
- var maxW = 0;
- var maxH = 0;
- var cwidth = circles[0].offsetWidth; //对象可见宽度
- var cheight = circles[0].offsetHeight; //对象可见高度
- //根据浏览器窗口的大小自动调节小球的运动空间
- window.onresize = function() {
- maxW = window.innerWidth - circles[0].clientWidth; //小球运动的最大宽度
- maxH = window.innerHeight - circles[0].clientHeight; //小球运动的最大高度
- main.style.width = window.innerWidth + "px";
- main.style.height = window.innerHeight + "px";
- }
- onresize();
- //数组对象的初始化
- for (var i = 0; i < circles.length; i++) {
- arr = [];
- for (var j = 0; j < 6; j++) {
- color[j] = st[Math.floor(Math.random() * 16)];
- }
- arr.x = Math.floor(Math.random() * (maxW + 1)); //初始x坐标
- arr.y = Math.floor(Math.random() * (maxH + 1)); //初始y坐标
- arr.cx = arr.x + circles[0].offsetWidth / 2; //圆心x坐标
- arr.cy = arr.y + circles[0].offsetHeight / 2; //圆心y坐标
- arr.movex = Math.floor(Math.random() * 2); //x轴移动方向
- arr.movey = Math.floor(Math.random() * 2); //y轴移动方向
- arr.speed = 2 + Math.floor(Math.random() * 5); //随机生成2-6之间的移动速度,如果在做项目的时候,这种随即生成的速度不想用的话,可以直接给speed赋值,
- 球的速度即可。如以下代码:
- //arr.speed = 1.5;
- arr.timer = null; //计时器
- arr.index = i; //索引值
- json.push(arr);
- circles[i].style.left = arr.x + "px"; //小球位置初始化
- circles[i].style.top = arr.y + "px"; //小球位置初始化
- }
- //碰撞函数
- function crash(a) {
- var ball1x = json[a].cx;
- var ball1y = json[a].cy;
- for (var i = 0; i < json.length; i++) {
- if (i != a) {
- var ball2x = json[i].cx;
- var ball2y = json[i].cy;
- //圆心距离的平方
- var len = (ball1x - ball2x) * (ball1x - ball2x) + (ball1y - ball2y) * (ball1y - ball2y);
- if (len <= cwidth * cwidth) {
- //小球位置的判断,发生碰撞反应
- if (ball1x > ball2x) {
- if (ball1y > ball2y) {
- json[a].movex = 1;
- json[a].movey = 1;
- } else if (ball1y < ball2y) {
- json[a].movex = 1;
- json[a].movey = 0;
- } else {
- json[a].movex = 1;
- }
- } else if (ball1x < ball2x) {
- if (ball1y > ball2y) {
- json[a].movex = 0;
- json[a].movey = 0;
- } else if (ball1y < ball2y) {
- json[a].movex = 0;
- json[a].movey = 1;
- } else {
- json[a].movex = 0;
- }
- } else {
- if (ball1y > ball2y) {
- json[a].movey = 1;
- } else if (ball1y < ball2y) {
- json[a].movey = 0;
- }
- }
- }
- }
- }
- }
- //移动函数
- function move(circle) {
- circle.timer = setInterval(function() {
- if (circle.movex == 1) {
- circle.x += circle.speed;
- if (circle.x + circle.speed >= maxW) { //防止小球出界
- circle.x = maxW;
- circle.movex = 0; //小球运动方向发生改变
- }
- } else {
- circle.x -= circle.speed;
- if (circle.x - circle.speed <= 0) {
- circle.x = 0;
- circle.movex = 1;
- }
- }
- if (circle.movey == 1) {
- circle.y += circle.speed;
- if (circle.y + circle.speed >= maxH) {
- circle.y = maxH;
- circle.movey = 0;
- }
- } else {
- circle.y -= circle.speed;
- if (circle.y - circle.speed <= 0) {
- circle.y = 0;
- circle.movey = 1;
- }
- }
- circle.cx = circle.x + circles[0].offsetWidth / 2; //小球每一次运动圆心都会发生改变
- circle.cy = circle.y + circles[0].offsetHeight / 2;
- circles[circle.index].style.left = circle.x + "px"; //小球位置重定位
- circles[circle.index].style.top = circle.y + "px";
- crash(circle.index);
- },
- 15);
- }
- //对每一个小球绑定计时器,让小球动起来
- for (var i = 0; i < circles.length; i++) {
- move(json[i]);
- }
- </script>
其实,我们通过上面的代码就可以完全实现一个小球碰撞检测的功能了。但是仅仅是上面的代码,还是会存在一定的bug,就是当整个网站存在右侧滚动条时,当小球碰到屏幕右侧的时候,会出现一瞬的横向滚动条,这就是做网站比较忌讳的了,横向滚动条的出现太丑了。所以我们可以通过以下代码来解决。
- //滚动条宽度计算函数
- function getScrollbarWidth() {
- var oP = document.createElement("p"),
- styles = {
- width: "100px",
- height: "100px",
- overflowY: "scroll"
- }, i, scrollbarWidth;
- for (i in styles) oP.style[i] = styles[i];
- document.body.appendChild(oP);
- scrollbarWidth = oP.offsetWidth - oP.clientWidth;
- oP.remove();
- return scrollbarWidth;
- }
以上是一个计算滚动条宽度的函数,此函数可以计算右侧滚动条的宽度,我们只需要在“根据浏览器窗口的大小自动调节小球的运动空间”上面,调用此函数
var scrollbarWidth = getScrollbarWidth(); 再修改小球的最大运动宽度 maxW=window.innerWidth-circles[0].clientWidth-scrollbarWidth ;这样这个bug就修改好了。
这个是我在做项目时的亲身经历,觉得这个写得特别好用,就拿过来与大家分享一下。希望对大家有那么一点点儿帮助吧!!最后还要感谢一下“敲代码不爱找bug的妹子”帮我解决了一个大问题。。
来源: http://www.cnblogs.com/interesting-me/p/7818632.html