为什么 MatterJS 物理坐标偏移 DOM 个元素?

Why do MatterJS physics coordinates have offset with DOM elements?

我是 运行 MatterJS 物理模拟,通过向物理引擎添加盒子,同时创建具有相同尺寸的 DOM 元素。

然后,我循环遍历物理框以获取它们的坐标。然后我使用这些坐标来定位相应的 DOM 元素。这似乎工作正常,只是我的静态“地面”框周围似乎有一个 10 像素的不可见半径?

我的盒子是 40x40 像素。地面为 400 像素。盒子在 350 像素处停止下落。那么为什么会有 10 个像素的差异?

Here is an example of the issue in CodePen

编辑:如果我在 canvas 中呈现相同的框,则不存在差异。 Codepen Canvas

class Box {
  constructor(world, x, y, w, h, options) {
    // add box to physics simulation
    this.physicsBox = Matter.Bodies.rectangle(x, y, w, h, 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, 40, 40),
    new Box(engine.world, 320, 70, 40, 40),
    new Box(engine.world, 0, 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, y, w, h, 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, 40, 40),
    new Box(engine.world, 320, 70, 40, 40),
    new Box(engine.world, 0, 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>