原生js做的小demo,实现小球碰撞模拟(适配各种屏幕)
作者:liushuai
HTML:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>随机生成div</title>
<style>
html{
height: 100%;
}
body{
width:100%;
margin:0;
padding:0;
height:100%;
}
div.wrap{
height:100%;
position: relative;
overflow: hidden;
margin:0;
padding:0;
}
div:not(.wrap){
border-radius: 50%;
/*-webkit-animation:tanslateAni 5000ms infinite linear alternate;*/
/*transition: all 10000ms linear;*/
}
div:nth-of-type(2){
-webkit-animation-delay:2000ms;
}
div:nth-of-type(3){
-webkit-animation-delay:4000ms;
}
div:nth-of-type(4){
-webkit-animation-delay:-1000ms;
}
@-webkit-keyframes tanslateAni{
0% {-webkit-transform:rotate(10deg) translate3d(0px,0px,0)}
35% {-webkit-transform:rotate(0deg) translate3d(20px,0px,0)}
70% {-webkit-transform:rotate(-10deg) translate3d(0px,0px,0)}
100% {-webkit-transform:rotate(0deg) translate3d(-20px,0px,0)}
}
</style>
</head>
<body>
<div class="wrap" id='parent'></div>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="ball.js">
</script>
</body>
</html>
js:
var elWidth=110;
var containerWidth;
var color=['red','green','blue','black','yellow'];//随机的颜色
var ballNum=20;
//var pageHeight=window.screen.height;
var pageHeight=document.body.clientHeight;
//var pageWidth=window.screen.width;
var pageWidth=document.body.clientWidth;
containerWidth=pageWidth;
var sizeRange=60;
var balls=[];
window.onload=function(){
createBalls(elWidth+sizeRange,pageWidth,pageHeight,ballNum);
setInterval(function(){ballHit(balls,pageWidth,pageHeight)},30)
}
//生成虚拟网格
function createTable(ballWidth,pageWidth,pageHeight){
var col=Math.floor(pageWidth/ballWidth);
var marginH=pageWidth%ballWidth;
var marginV=pageHeight%ballWidth;
var row=Math.floor(pageHeight/ballWidth);
var total=col*row;
var ballMap=[];
for(var i=0;i<total;i++){//网格map存入一维数组
//top、left值有较大偏差原因:/、%运算为小数,与Java不同
ballMap[i]={left:marginH/2+Math.floor(i%col)*ballWidth,top:marginV/2+Math.floor(i/col)*ballWidth}
}
return ballMap;
}
//生成小球
var spaceIndex=25;
function createBalls(ballWidth,pageWidth,pageHeight,ballNum){
var ballMap=createTable(ballWidth,pageWidth,pageHeight);
var range=ballMap.length
if(ballNum>=range-spaceIndex){
ballNum=range-spaceIndex;
}
var ballsData=[];
var ballIndex;
ballIndex=getRandom(0,range,ballNum);
for(var i=0;i<ballIndex.length;i++){
ballsData[i]=ballMap[ballIndex[i]];
}
renderBalls(ballsData,ballNum);
}
//渲染小球
function renderBalls(ballData,ballNum){
for(var i=0;i<ballNum;i++){
var divBall=createEl('div')
//(待改进),用面向对象方式改进
balls.push({el:divBall,left:ballData[i].left,top:ballData[i].top,
vx:Math.random()*6-3,vy:Math.random()*6-3,
raduis:parseInt(divBall.style.width)/2});
}
for(var j=0;j<ballNum;j++){
balls[j].el.style.left=balls[j].left+'px';
balls[j].el.style.top=balls[j].top+'px';
}
}
//随机数去重
function noRepeat(arr,newNum,range){
var isRepeat=false;
for(var i=0;i<arr.length;i++){
if(newNum==arr[i]){
isRepeat=true;
break;
}
}
if(isRepeat){
newNum=Math.floor(Math.random()*range);
noRepeat(arr,newNum,range);
}else{
return newNum;
}
}
//随机数去重工具函数2
function getRandom(min,max,n){
if (n > (max - min + 1) || max < min) {
return null;
}
var result = [];
var count = 0;
while(count < n) {
var num =Math.floor(Math.random() * (max - min)) + min;
var flag = true;
for (var j = 0; j < n; j++) {
if(num == result[j]){
flag = false;
break;
}
}
if(flag){
result[count] = num;
count++;
}
}
return result;
}
//随机生成一个dom元素
function createEl(el,text){
var elment=document.createElement(el);
document.getElementById('parent').appendChild(elment);
var len=Math.ceil(Math.random()*sizeRange);
elment.style.width=len+elWidth+'px';
elment.style.height=len+elWidth+'px';
elment.style.backgroundColor=color[Math.floor(Math.random()*5)];
elment.style.position='absolute';
elment.innerHTML=text||"";
return elment;
}
function moveBall(balls){
for(var i=0;i<balls.length;i++){
balls[i].left+=balls[i].vx;
balls[i].top+=balls[i].vy;
balls[i].el.style.left=balls[i].left+'px';
balls[i].el.style.top=balls[i].top+'px';
}
}
var spring= 1;//球与球之间弹性系数
var bounce=-1;//球与边缘之间弹性系数
function ballHit(balls,pageWidth,pageHeight){
//检测边缘
for(var i=0;i<balls.length;i++){
if(balls[i].left<=0||balls[i].left>=pageWidth-2*balls[i].raduis){
balls[i].vx*=bounce;
}
if(balls[i].top<=0||balls[i].top>=pageHeight-2*balls[i].raduis){
balls[i].vy*=bounce;
}
}
//检测小球与小球
for (i=0;i<balls.length;i++) {
var ball1=balls[i];
ball1.x=ball1.left+ball1.raduis;
ball1.y=ball1.top+ball1.raduis;
for (j=i+1;j<balls.length;j++) {
var ball2=balls[j];
ball2.x=ball2.left+ball2.raduis;
ball2.y=ball2.top+ball2.raduis;
dx=ball2.x-ball1.x;
dy=ball2.y-ball1.y;
var dist=Math.sqrt(dx*dx + dy*dy);
var misDist=ball1.raduis+ball2.raduis;
if(dist < misDist) {
var angle=Math.atan2(dy,dx);
tx=ball1.x+Math.cos(angle) * misDist;
ty=ball1.y+Math.sin(angle) * misDist;
ax=(tx-ball2.x) * spring;
ay=(ty-ball2.y) * spring;
ball1.vx-=ax;
ball1.vy-=ay;
ball2.vx+=ax;
ball2.vy+=ay;
}
}
}
moveBall(balls);
}
点击查看更多内容
15人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦