问题描述
我通过向物理引擎添加框来运行 MatterJS 物理模拟,同时创建具有相同尺寸的 DOM 元素。
然后,我将遍历物理框以获取它们的坐标。然后我使用这些坐标来定位相应的 DOM 元素。这似乎工作正常,除了我的静态“地面”框似乎有一个 10 像素的不可见半径围绕它?
我的盒子是 40x40 像素。地面为 400 像素。盒子在 350 像素处停止下降。那么为什么会有 10 个像素的差异呢?
Here is an example of the issue in CodePen
编辑:如果我在画布中渲染相同的框,则不存在差异。 Codepen Canvas
class Box {
constructor(world,x,y,w,h,options) {
// add Box to physics simulation
this.physicsBox = Matter.Bodies.rectangle(x,options);
Matter.Composite.add(world,this.physicsBox);
// add DOM Box at the same coordinates
this.div = document.createElement("Box");
document.body.appendChild(this.div);
this.div.style.width = w + "px";
this.div.style.height = h + "px";
this.update();
}
update() {
let pos = this.physicsBox.position;
let angle = this.physicsBox.angle;
let degrees = angle * (180 / Math.PI);
this.div.style.transform = `translate(${pos.x}px,${pos.y}px) rotate(${degrees}deg)`;
}
}
let engine;
let Boxes = [];
setupMatter();
addobjects();
gameLoop();
function setupMatter() {
engine = Matter.Engine.create();
}
function addobjects() {
Boxes.push(
new Box(engine.world,250,20,40,40),new Box(engine.world,300,350,320,70,400,800,60,{ isstatic: true })
);
}
function gameLoop() {
// update the physics world
Matter.Engine.update(engine,1000 / 60);
// update the DOM world
for (let b of Boxes) {
b.update();
}
requestAnimationFrame(() => this.gameLoop());
}
html,body {
background-color: #4b4b4b;
color: white;
margin: 0px;
padding: 0px;
}
Box {
margin: 0px;
padding: 0px;
Box-sizing: border-Box;
position: absolute;
display: block;
background-color: rgba(45,188,232,0.687);
transform-origin: 20px 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script>
解决方法
问题在于,当您为框设置 x,y 位置时,您没有考虑高度。所以显示的位置与实际位置不匹配。
我真正改变的唯一一行是 this.div.style.transform = `translate(${pos.x}px,${pos.y}px) rotate(${degrees}deg)`;
。
10 像素的差异是因为 60 像素深的底部显示的 30 像素(深度的一半)太低,而 40 像素深的框显示的太低 20 像素 - 底部上方的净 10 像素。当我尝试将高度设置为 1px 时,一切看起来都不错,这就是我发现错误的方式。
class Box {
constructor(world,x,y,w,h,options) {
// add box to physics simulation
this.physicsBox = Matter.Bodies.rectangle(x,options);
Matter.Composite.add(world,this.physicsBox);
// add DOM box at the same coordinates
this.div = document.createElement("box");
document.body.appendChild(this.div);
this.div.style.width = w + "px";
this.div.style.height = h + "px";
this.width = w;
this.height = h;
this.update();
}
update() {
let pos = this.physicsBox.position;
let angle = this.physicsBox.angle;
let degrees = angle * (180 / Math.PI);
this.div.style.transform = `translate(${pos.x - (this.width/2)}px,${pos.y-(this.height/2)}px) rotate(${degrees}deg)`;
}
}
let engine;
let boxes = [];
setupMatter();
addObjects();
gameLoop();
function setupMatter() {
engine = Matter.Engine.create();
}
function addObjects() {
boxes.push(
new Box(engine.world,250,20,40,40),new Box(engine.world,300,350,320,70,400,800,60,{ isStatic: true })
);
}
function gameLoop() {
// update the physics world
Matter.Engine.update(engine,1000 / 60);
// update the DOM world
for (let b of boxes) {
b.update();
}
requestAnimationFrame(() => this.gameLoop());
}
html,body {
background-color: #4b4b4b;
color: white;
margin: 0px;
padding: 0px;
}
box {
margin: 0px;
padding: 0px;
box-sizing: border-box;
position: absolute;
display: block;
background-color: rgba(45,188,232,0.687);
transform-origin: 20px 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script>