1 回答

TA貢獻2003條經驗 獲得超2個贊
但是,我無法理解如何像上面的示例那樣在 Bodies 矩形內傳遞 HTML 元素。
這不是這個例子所做的。當無頭運行時,Matter.js 處理物理而不知道它是如何呈現的。每個動畫幀,您可以使用 MJS 主體的當前位置并重新定位您的元素(或在畫布上繪制等)以反映 MJS 的世界觀。
向 MJS 提供根元素似乎會破壞單向數據流,但這只是為了通知 MJS 有關鼠標位置和點擊等事件的信息——不要與渲染混淆。
這是一個希望能使這一點更清楚的最小示例:
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.Composite.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.19.0/matter.min.js"></script>
<div id="box"></div>
<div id="ground"></div>
反應
React 改變了工作流程,但基本概念是相同的——MJS 主體數據從 MJS 后端單向流向渲染前端,因此從 MJS 的角度來看,一切都與上面的普通示例相同。大部分工作是設置refs并useEffect正確地與requestAnimationFrame.
const {Fragment, useEffect, useRef} = React;
const Scene = () => {
const requestRef = useRef();
const boxRef = useRef();
const groundRef = useRef();
const engineRef = useRef();
const animate = () => {
engineRef.current = Matter.Engine.create();
const engine = engineRef.current;
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, // x
200, // y
400, // w
120, // h
{isStatic: true}
);
const mouseConstraint = Matter.MouseConstraint.create(
engine,
{element: document.body}
);
Matter.Composite.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);
Matter.Engine.clear(engineRef.current);
// see https://github.com/liabru/matter-js/issues/564
// for additional cleanup if using MJS renderer/runner
};
}, []);
return (
<Fragment>
<div id="box" ref={boxRef}></div>
<div id="ground" ref={groundRef}></div>
</Fragment>
);
};
ReactDOM.createRoot(document.querySelector("#app")).render(
<Scene />
);
#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 crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
<div id="app"></div>
請注意,這些只是概念驗證。在它們能夠支持更多涉及的用例之前,可能需要更多的工作來設置抽象。
添加回答
舉報