像电脑屏保一样的气泡碰撞效果
像电脑屏保一样的气泡碰撞效果
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>Title</title> 7 <style> 8 * { 9 margin: 0; 10 padding: 0 11 } 12 13 #main { 14 margin: 0 auto; 15 position: relative; 16 background-color: #fff 17 } 18 19 #main div { 20 position: absolute; 21 width: 100px; 22 height: 100px; 23 overflow: hidden; 24 -moz-border-radius: 50%; 25 -webkit-border-radius: 50%; 26 border-radius: 50%; 27 background: blue; 28 } 29 </style> 30 </head> 31 32 <body> 33 <div id="main"> 34 <div></div> 35 <div></div> 36 <div></div> 37 <div></div> 38 <div></div> 39 <div></div> 40 <div></div> 41 <div></div> 42 <div></div> 43 <div></div> 44 </div> 45 46 </body> 47 48 </html> 49 <script> 50 var main = document.getElementById('main'); //获取运动边界和10个div 51 var circles = main.getElementsByTagName('div'); 52 var container = []; //存放10个球的每个具体信息,包括坐标,速度等值 53 var arr = []; 54 var maxW = 0; //初始化运动的最大宽和高,初始定义0 55 var maxH = 0; 56 var cwidth = circles[0].offsetWidth; //小球的直径 57 58 59 //根据浏览器窗口的大小自动调节小球的运动空间 60 window.onresize = function() { 61 maxW = window.innerWidth - circles[0].clientWidth; //为了让小球不卡在浏览器边缘, 62 maxH = window.innerHeight - circles[0].clientHeight; // 所以要减去自身的宽高 63 main.style.width = window.innerWidth + 'px'; //将容器的宽高和文档显示区宽高相等 64 main.style.height = window.innerHeight + 'px'; 65 }; 66 onresize(); 67 //数组对象的初始化 68 for (var i = 0; i < circles.length; i++) { 69 arr = []; 70 arr.x = Math.floor(Math.random() * (maxW + 1)); //初始x坐标 71 arr.y = Math.floor(Math.random() * (maxH + 1)); //初始y坐标 72 arr.cx = arr.x + circles[0].offsetWidth / 2; //圆心x坐标 73 arr.cy = arr.y + circles[0].offsetHeight / 2; //圆心y坐标 74 arr.movex = Math.floor(Math.random() * 2); //x轴移动方向 75 arr.movey = Math.floor(Math.random() * 2); //y轴移动方向 76 arr.speed = 2 + Math.floor(Math.random() * 4); //随机速度 77 arr.timer = null; //计时器 78 arr.index = i; //索引值 79 container.push(arr); //存放所有的属性值 80 circles[i].style.left = arr.x + 'px'; //小球位置初始化 81 circles[i].style.top = arr.y + 'px'; 82 } 83 84 //碰撞函数 85 function crash(a) { 86 var ball1x = container[a].cx; //在数组中任意球的圆心坐标 87 var ball1y = container[a].cy; //思路:先随便拿一个球,然后遍历所有球,拿这个球和所有球的圆心距离比较 88 for (var i = 0; i < container.length; i++) { 89 if (i !== a) { //判断取出来的球不是本身,才能和其他球进行距离判断 90 var ball2x = container[i].cx; //将其他球的圆心坐标赋值给球2 91 var ball2y = container[i].cy; 92 //圆心距 求两个点之间的距离,开平方 93 var distence = Math.sqrt((ball1x - ball2x) * (ball1x - ball2x) + (ball1y - ball2y) * (ball1y - ball2y)); 94 if (distence <= cwidth) { //球心距离和求直径比较 95 if (ball1x > ball2x) { //当前位于未知求的右方 96 if (ball1y > ball2y) { //预设未知球撞当前球,然后当前球改变运动 97 container[a].movex = 1; //1表示为正值,对应的右和下 98 container[a].movey = 1; //0表示为负值,对应的左和上 99 } else if (ball1y < ball2y) { 100 container[a].movex = 1; 101 container[a].movey = 0; 102 } else { 103 container[a].movex = 1; 104 } 105 } else if (ball1x < ball2x) { 106 if (ball1y > ball2y) { 107 container[a].movex = 0; 108 container[a].movey = 0; 109 } else if (ball1y < ball2y) { 110 container[a].movex = 0; 111 container[a].movey = 1; 112 } else { 113 container[a].movex = 0; 114 } 115 } else { 116 if (ball1y > ball2y) { 117 container[a].movey = 1; 118 } else if (ball1y < ball2y) { 119 container[a].movey = 0; 120 } 121 } 122 } 123 } 124 125 } 126 } 127 128 //移动函数 129 function move(balls) { //每个球单独有定时器 130 balls.timer = setInterval(function() { 131 if (balls.movex === 1) { //如果往右跑,则一直加速度,碰到边界,改为反方向运动 132 balls.x += balls.speed; 133 if (balls.x + balls.speed >= maxW) { //防止小球出界 134 balls.x = maxW; 135 balls.movex = 0; //小球运动方向发生改变 136 } 137 } else { 138 balls.x -= balls.speed; // 1和0表示正反方向 139 if (balls.x - balls.speed <= 0) { 140 balls.x = 0; 141 balls.movex = 1; 142 } 143 } 144 if (balls.movey === 1) { 145 balls.y += balls.speed; 146 if (balls.y + balls.speed >= maxH) { 147 balls.y = maxH; 148 balls.movey = 0; 149 } 150 } else { 151 balls.y -= balls.speed; 152 if (balls.y - balls.speed <= 0) { 153 balls.y = 0; 154 balls.movey = 1; 155 } 156 } 157 balls.cx = balls.x + circles[0].offsetWidth / 2; //小球圆心等于:运动中x的值加上自身的半径 158 balls.cy = balls.y + circles[0].offsetHeight / 2; 159 circles[balls.index].style.left = balls.x + 'px'; //小球相对于屏幕的位置 160 circles[balls.index].style.top = balls.y + 'px'; 161 crash(balls.index); //每个小球进行碰撞检测 162 }, 25); 163 } 164 165 //对每一个小球绑定计时器,让小球动起来 166 for (var i = 0; i < container.length; i++) { 167 move(container[i]); 168 } 169 170 //红色气泡的单独效果 171 var red = document.getElementById('red'); //获取红色泡 172 var mouseOffsetX = 0, 173 mouseOffsetY = 0; //初始定义偏移值 174 var isDrag = false; //是否可拖动 175 red.addEventListener('mousedown', function(e) { //鼠标按下 176 var e = e || window.event; 177 mouseOffsetX = e.pageX - red.offsetLeft; //鼠标指针位置减去元素的左边距 178 mouseOffsetY = e.pageY - red.offsetTop; 179 isDrag = true; 180 }); 181 //鼠标移动 182 document.onmousemove = function(e) { //鼠标移动e 183 var e = e || window.event; 184 var mouseX = e.pageX; 185 var mouseY = e.pageY; 186 var moveX = 0, 187 moveY = 0; 188 if (isDrag === true) { 189 moveX = mouseX - mouseOffsetX; //移动的距离等于鼠标指针减去上面获取的差值 190 moveY = mouseY - mouseOffsetY; 191 //限定移动范围 192 var PW = document.documentElement.clientWidth; //窗口的宽高 193 var PH = document.documentElement.clientHeight; 194 195 var redW = red.offsetWidth; //元素红色泡泡的自身的宽高 196 var redH = red.offsetHeight; 197 198 var maxX = PW - redW; //最大的宽度为窗口可视区宽减去自身的宽 199 var maxY = PH - redH; 200 moveX = Math.min(maxX, Math.max(0, moveX)); // 取值范围 201 moveY = Math.min(maxY, Math.max(0, moveY)); 202 red.style.left = moveX + 'px'; 203 red.style.top = moveY + 'px'; 204 205 //下面部分是判断部分 206 var _redx = parseInt(red.style.left + redW / 2); //红球的球心坐标 207 var _redy = parseInt(red.style.top + redH / 2); 208 209 var dsetination = circles[0].offsetWidth / 2 + redW / 2; //红球和蓝球的半径之和 210 for (var i = 0; i < container.length; i++) { //取出数组中所有球 211 var bx = container[i].cx; //球的圆心坐标 212 var by = container[i].cy; 213 var dis1 = (_redx - bx) * (_redx - bx) + (_redy - by) * (_redy - by); //两个圆心之间的距离 214 var dis2 = Math.floor(Math.sqrt(dis1)); //开平方后再取整 215 if (dis2 <= dsetination) { //球心距离和求直径比较 216 if (_redx > bx) { //当前位于未知求的右方 217 if (_redy > by) { //预设未知球撞当前球,然后被撞击球改变运动 218 container[i].movex = 0; 219 container[i].movey = 0; 220 } else if (_redy < by) { 221 container[i].movey = 1; 222 container[i].movex = 0; 223 } else if (_redy = by) { 224 container[i].movex = 0; 225 } 226 } else if (_redx < bx) { //红球在蓝球的左下方 227 if (_redy > by) { 228 container[i].movex = 1; 229 container[i].movey = 0; 230 } else if (_redy < by) { //红球在蓝球的左上方 231 container[i].movex = 1; 232 container[i].movey = 1; 233 } else if (j_redy = by) { 234 container[i].movex = 1; 235 } 236 } 237 } 238 } 239 } 240 }; 241 //鼠标松开 242 document.onmouseup = function() { 243 isDrag = false; 244 }; 245 </script>
版权声明:本文为l-y-z原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。