关于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>

但经测试元素得碰撞区域比元素本身要大很多,如图

关于vue检测多元素碰撞的问题?

我感觉问题出在这一句,不知道对不对,因为 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

回到顶部