Verwenden von Matter.js zum Rendern im DOM oder React

Lesezeit: 4 Minuten

Verwenden von Matterjs zum Rendern im DOM oder React
Waelmas

Ich möchte benutzerdefinierte HTML-Elemente als Bodies in Matter.js rendern. Ich verwende es in React, was ein wenig Komplexität hinzufügt, aber für mein Problem irrelevant ist.

Ich habe viel gesucht und das einzige Beispiel, das ich gefunden habe, war dieses hierdie zu verwenden scheint querySelector Um die Elemente auszuwählen, die im HTML-Code leben, verwenden Sie sie dann irgendwie innerhalb der Rechteckformen.

Der Teil, der die Arbeit zu erledigen scheint, ist der folgende:

var bodiesDom = document.querySelectorAll('.block');
var bodies = [];
for (var i = 0, l = bodiesDom.length; i < l; i++) {
    var body = Bodies.rectangle(
        VIEW.centerX,
        20, 
        VIEW.width*bodiesDom[i].offsetWidth/window.innerWidth, 
        VIEW.height*bodiesDom[i].offsetHeight/window.innerHeight
    );
    bodiesDom[i].id = body.id;
    bodies.push(body);
}
World.add(engine.world, bodies);

(der VIEW Variablen könnten nur Zufallszahlen sein, da sie die Form definieren)

Ich kann jedoch nicht verstehen, wie man ein HTML-Element innerhalb des Bodies-Rechtecks ​​wie im obigen Beispiel übergibt.

Idealerweise möchte ich komplexe HTML-Elemente haben, die mit der Physikwelt interagieren (wie eine kleine Box mit Schaltflächen usw.).

Irgendwelche Ideen, wie dies erreicht werden könnte? Oder können Sie die im Beispiel verwendete Methode erläutern, die es anscheinend geschafft hat?

1647108726 697 Verwenden von Matterjs zum Rendern im DOM oder React
ggorlen

Ich kann jedoch nicht verstehen, wie man ein HTML-Element innerhalb des Bodies-Rechtecks ​​wie im obigen Beispiel übergibt.

Das ist nicht ganz das, was das Beispiel tut. Beim kopflosen Ausführen verarbeitet Matter.js die Physik, ohne eine Ahnung zu haben, wie sie gerendert wird. Pro Animationsframe können Sie die aktuellen Positionen der MJS-Körper verwenden und Ihre Elemente neu positionieren (oder auf Leinwand zeichnen usw.), um die Sicht von MJS auf die Welt widerzuspiegeln.

Die Bereitstellung eines Root-Elements für MJS scheint den unidirektionalen Datenfluss zu unterbrechen, aber dies dient nur dazu, MJS über Ereignisse wie Mausposition und Klicks zu informieren – nicht zu verwechseln mit Rendering.

Hier ist ein Minimalbeispiel, um dies hoffentlich klarer zu machen:

const engine = Matter.Engine.create();  
const box = {
  body: Matter.Bodies.rectangle(150, 0, 40, 40),
  elem: document.querySelector("#box"),
  render() {
    const {x, y} = this.body.position;
    this.elem.style.top = `${y - 20}px`;
    this.elem.style.left = `${x - 20}px`;
    this.elem.style.transform = `rotate(${this.body.angle}rad)`;
  },
};
const ground = Matter.Bodies.rectangle(
  200, 200, 400, 120, {isStatic: true}
);
const mouseConstraint = Matter.MouseConstraint.create(
  engine, {element: document.body}
);
Matter.World.add(
  engine.world, [box.body, ground, mouseConstraint]
);
(function rerender() {
  box.render();
  Matter.Engine.update(engine);
  requestAnimationFrame(rerender);
})();
#box {
  position: absolute;
  background: #111;
  height: 40px;
  width: 40px;
  cursor: move;
}

#ground {
  position: absolute;
  background: #666;
  top: 140px;
  height: 120px;
  width: 400px;
}

html, body {
  position: relative;
  height: 100%;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
<div id="box"></div>
<div id="ground"></div>

Reagieren

React ändert den Arbeitsablauf, aber das grundlegende Konzept ist das gleiche – MJS-Body-Daten fließen unidirektional vom MJS-Back-End zum Rendering-Front-End, also ist aus MJS-Perspektive alles identisch mit dem obigen Vanilla-Beispiel. Die meiste Arbeit ist das Einrichten Refs und useEffect richtig für den Einsatz mit requestAnimationFrame.

#box {
  position: absolute;
  background: #111;
  height: 40px;
  width: 40px;
  cursor: move;
}

#ground {
  position: absolute;
  top: 140px;
  height: 120px;
  width: 400px;
  background: #666;
}

html, body {
  position: relative;
  height: 100%;
  margin: 0;
}
<script type="text/babel" defer>
const {Fragment, useEffect, useRef} = React;

const Scene = () => {
  const requestRef = useRef();
  const boxRef = useRef();
  const groundRef = useRef();

  const animate = () => {
    const engine = Matter.Engine.create();
    
    const box = {
      body: Matter.Bodies.rectangle(150, 0, 40, 40),
      elem: boxRef.current,
      render() {
        const {x, y} = this.body.position;
        this.elem.style.top = `${y - 20}px`;
        this.elem.style.left = `${x - 20}px`;
        this.elem.style.transform = `rotate(${this.body.angle}rad)`;
      },
    };
    const ground = Matter.Bodies.rectangle(
      200, 200, 400, 120, {isStatic: true}
    );
    const mouseConstraint = Matter.MouseConstraint.create(
      engine, {element: document.body}
    );
    Matter.World.add(
      engine.world, [box.body, ground, mouseConstraint]
    );
    
    (function rerender() {
      box.render();
      Matter.Engine.update(engine);
      requestRef.current = requestAnimationFrame(rerender);
    })();
  };
  
  useEffect(() => {
    animate();
    return () => cancelAnimationFrame(requestRef.current);
  }, []);
  
  return (
    <Fragment>
      <div id="box" ref={boxRef}></div>
      <div id="ground" ref={groundRef}></div>
    </Fragment>
  );
};

ReactDOM.render(<Scene />, document.body);

</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>

Beachten Sie, dass dies nur Proofs-of-Concept sind. Es wird wahrscheinlich mehr Arbeit zum Einrichten von Abstraktionen erforderlich sein, bevor sie komplexere Anwendungsfälle unterstützen können.

994760cookie-checkVerwenden von Matter.js zum Rendern im DOM oder React

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy