从度娘出得出如下代码:
<template>
<div id="wrap"></div>
</template>
<script>
export default {
data () {
return {
//获得wrapDiv
wrapDiv: null,
//定义数组存储所有的小球
balls: [],
title: ['11', '22', '33', '44', '55', '66', '77', '88']
}
},
created () {
this.$nextTick(function () {
this.wrapDiv = document.getElementById("wrap");
this.init()
})
},
methods: {
init () {
this.createBalls();
for (var i = 0; i < this.balls.length; i++) {
//将所有的小球传到函数中,来实现对小球的移动
this.moveBalls(this.balls[i]);
}
},
randomNum (m, n) {
return Math.floor(Math.random() * (n - m + 1) + m);
},
/**
* 生成一个随机颜色,并返回rgb字符串值
*/
randomColor () {
var r = this.randomNum(0, 255);
var g = this.randomNum(0, 255);
var b = this.randomNum(0, 255);
return "rgb(" + r + "," + g + "," + b + ")";
},
//生成小球函数
createBalls () {
for (var i = 0; i < this.title.length; i++) {
var ball = document.createElement("p");
//随机小球起始的X坐标和小球的Y坐标
ball.x = this.randomNum(0, 700);
ball.y = this.randomNum(0, 500);
//随机小球的移动速度
// ball.speed = this.randomNum(2, 5);
ball.speed = 0.4;
//随机小球移动的方向
if (Math.random() - 0.5 > 0) {
ball.xflag = true;
} else {
ball.xflag = false;
}
if (Math.random() - 0.5 > 0) {
ball.yflag = true;
} else {
ball.yflag = false;
}
//随机小球的背景颜色
ball.style.backgroundColor = this.randomColor();
// ball.innerHTML = i + 1;
ball.innerHTML = this.title[i];
//将小球插入当wrapDiv中
this.wrapDiv.appendChild(ball);
//将所有的小球存储到数组中
this.balls.push(ball);
}
},
moveBalls (ballObj) {
var _this = this
setInterval(function () {
ballObj.style.top = ballObj.y + "px";
ballObj.style.left = ballObj.x + "px";
//判断小球的标志量,对小球作出相应操作
if (ballObj.yflag) {
//小球向下移动 下边界
ballObj.y += ballObj.speed;
if (ballObj.y >= 500 - ballObj.offsetWidth) {
ballObj.y = 500 - ballObj.offsetWidth;
ballObj.yflag = false;
}
} else {
//小球向上移动
ballObj.y -= ballObj.speed;
if (ballObj.y <= 0) {
ballObj.y = 0;
ballObj.yflag = true;
}
}
if (ballObj.xflag) {
//小球向右移动 右边界
ballObj.x += ballObj.speed;
if (ballObj.x >= 700 - ballObj.offsetHeight) {
ballObj.x = 700 - ballObj.offsetHeight;
ballObj.xflag = false;
}
} else {
//小球向左移动
ballObj.x -= ballObj.speed;
if (ballObj.x <= 0) {
ballObj.x = 0;
ballObj.xflag = true;
}
}
_this.crash(ballObj);
}, 10);
},
crash (ballObj) {
var x1, y1, x2, y2;
//通过传过来的小球对象来获取小球的X坐标和Y坐标
x1 = ballObj.x;
y1 = ballObj.y;
for (var i = 0; i < this.balls.length; i++) {
//确保不和自己对比
if (ballObj != this.balls[i]) {
x2 = this.balls[i].x;
y2 = this.balls[i].y;
//判断位置的平方和小球的圆心坐标的关系 相距多长时触碰反弹
if (Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + 500 <= Math.pow(ballObj.offsetWidth + this.balls[i].offsetWidth, 2)) {
//判断传过来的小球对象,相对于碰撞小球的哪个方位
if (ballObj.x < this.balls[i].x) {
if (ballObj.y < this.balls[i].y) {
//小球对象在被碰小球的左上角
ballObj.yflag = false;
ballObj.xflag = false;
} else if (ballObj.y > this.balls[i].y) {
//小球对象在被碰小球的左下角
ballObj.xflag = false;
ballObj.yflag = true;
} else {
//小球对象在被撞小球的正左方
ballObj.xflag = false;
}
} else if (ballObj.x > this.balls[i].x) {
if (ballObj.y < this.balls[i].y) {
//小球对象在被碰撞小球的右上方
ballObj.yflag = false;
ballObj.xflag = true;
} else if (ballObj.y > this.balls[i].y) {
//小球对象在被碰撞小球的右下方
ballObj.xflag = true;
ballObj.yflag = true;
} else {
//小球对象在被撞小球的正右方
ballObj.xflag = true;
}
} else if (ballObj.y > this.balls[i].y) {
//小球对象在被撞小球的正下方
ballObj.yflag = true;
} else if (ballObj.y < this.balls[i].y) {
//小球对象在被撞小球的正上方
ballObj.yflag = false;
}
}
}
}
}
}
}
</script>
但经测试元素得碰撞区域比元素本身要大很多,如图
我感觉问题出在这一句,不知道对不对,因为 Math.pow 算的是平方
if (Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2) + 500 <= Math.pow(ballObj.offsetWidth + this.balls[i].offsetWidth, 2))
经尝试后效果仍然无法达到触碰元素本身边缘弹开得效果,还望指点迷津,谢谢!
用原生js写了下,你的判断逻辑写太多了,那些正上方正下方可以看成是左上角右下角的特例子,其实碰撞逻辑就是Math.abs(x1 - x2) <= width && Math.abs(y1 - y2) <= height; width,heigth指的就是当前元素的宽高