亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 Matter.js 渲染到 DOM 或 React

使用 Matter.js 渲染到 DOM 或 React

小唯快跑啊 2023-03-03 19:32:14
我想在 Matter.js 中將自定義 HTML 元素呈現為主體。我在 React 中使用它,這增加了一些復雜性,但它與我的問題無關。我搜索了很多,我找到的唯一示例是這里的這個,它似乎用于querySelector選擇 HTML 代碼中的元素,然后以某種方式在矩形形狀內使用它們。似乎在做這項工作的部分如下: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);(VIEW那里的變量在定義形狀時可能只是隨機數)但是,我無法理解如何像上面的示例那樣在 Bodies 矩形內傳遞 HTML 元素。理想情況下,我希望有復雜的 HTML 元素與物理世界交互(比如帶有按鈕的小盒子等)。關于如何實現這一目標的任何想法?或者,您能否解釋一下示例中使用的似乎已經成功解決的方法?
查看完整描述

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>

請注意,這些只是概念驗證。在它們能夠支持更多涉及的用例之前,可能需要更多的工作來設置抽象。



查看完整回答
反對 回復 2023-03-03
  • 1 回答
  • 0 關注
  • 278 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號