关于vue检测多元素碰撞的问题?
从度娘出得出如下代码:
<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))
经尝试后效果仍然无法达到触碰元素本身边缘弹开得效果,还望指点迷津,谢谢!
回答:
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html,
body {
height: 100%;
}
body {
margin: 0;
}
* {
box-sizing: border-box;
}
#wrap {
position: relative;
height: 100%;
}
#wrap p {
width: 100px;
height: 100px;
margin: 0;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<div id="wrap"></div>
<script>
let wrapDiv = null;
//定义数组存储所有的小球
const balls = [];
const title = ['11', '22', '33', '44', '55', '66', '77', '88'];
wrapDiv = document.getElementById('wrap');
const { width, height } = wrapDiv.getBoundingClientRect();
init();
function init() {
createBalls();
for (var i = 0; i < balls.length; i++) {
//将所有的小球传到函数中,来实现对小球的移动
moveBalls(balls[i]);
}
}
function randomNum(m, n) {
return Math.floor(Math.random() * (n - m + 1) + m);
}
/**
* 生成一个随机颜色,并返回rgb字符串值
*/
function randomColor() {
var r = randomNum(0, 255);
var g = randomNum(0, 255);
var b = randomNum(0, 255);
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
//生成小球函数
function createBalls() {
const fragment = document.createDocumentFragment();
for (var i = 0; i < title.length; i++) {
var ball = document.createElement('p');
//随机小球起始的X坐标和小球的Y坐标
ball.x = randomNum(0, width - 100);
ball.y = randomNum(0, height - 100);
//随机小球的移动速度
// 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 = randomColor();
// ball.innerHTML = i + 1;
ball.innerHTML = title[i];
//将小球插入当wrapDiv中
fragment.appendChild(ball);
//将所有的小球存储到数组中
balls.push(ball);
}
wrapDiv.appendChild(fragment);
}
function moveBalls(ballObj) {
setInterval(function () {
ballObj.style.top = ballObj.y + 'px';
ballObj.style.left = ballObj.x + 'px';
//判断小球的标志量,对小球作出相应操作
if (ballObj.yflag) {
//小球向下移动 下边界
ballObj.y += ballObj.speed;
// 100指的是元素高度
if (ballObj.y >= height - 100) {
ballObj.y = height - 100;
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;
// 100指的是元素宽度
if (ballObj.x >= width - 100) {
ballObj.x = width - 100;
ballObj.xflag = false;
}
} else {
//小球向左移动
ballObj.x -= ballObj.speed;
if (ballObj.x <= 0) {
ballObj.x = 0;
ballObj.xflag = true;
}
}
crash(ballObj);
}, 10);
}
function crash(ballObj) {
var x1, y1, x2, y2;
//通过传过来的小球对象来获取小球的X坐标和Y坐标
x1 = ballObj.x;
y1 = ballObj.y;
for (var i = 0; i < balls.length; i++) {
//确保不和自己对比
if (ballObj != balls[i]) {
x2 = balls[i].x;
y2 = balls[i].y;
// 100分别指的是当前元素宽高,x1 - x2小于宽度并且y1-y2小于高度
if (Math.abs(x1 - x2) <= 100 && Math.abs(y1 - y2) <= 100) {
//判断传过来的小球对象,相对于碰撞小球的哪个方位
if (x1 <= x2) {
if (y1 <= y2) {
//小球对象在被碰小球的左上角
ballObj.yflag = false;
ballObj.xflag = false;
} else {
//小球对象在被碰小球的左下角
ballObj.xflag = false;
ballObj.yflag = true;
}
} else {
if (y1 < y2) {
//小球对象在被碰撞小球的右上方
ballObj.yflag = false;
ballObj.xflag = true;
} else {
//小球对象在被碰撞小球的右下方
ballObj.xflag = true;
ballObj.yflag = true;
}
}
}
}
}
}
</script>
</body>
</html>
用原生js写了下,你的判断逻辑写太多了,那些正上方正下方可以看成是左上角右下角的特例子,其实碰撞逻辑就是Math.abs(x1 - x2) <= width && Math.abs(y1 - y2) <= height; width,heigth指的就是当前元素的宽高
回答:
把元素p css内置的padding设置为0 padding 0; margin:0 box-sizing:border-box
以上是 关于vue检测多元素碰撞的问题? 的全部内容, 来源链接: utcz.com/p/933507.html