自定义渲染器的Matter.js运行速度翻倍问题求助
解决Matter.js点击文本后场景速度翻倍的问题
你的问题核心是每次点击文本时都新建了一个独立的渲染循环,还重复更新物理引擎——初始代码已经有一个全局循环在跑引擎更新,每点一次就多一个循环,每个循环都执行Matter.Engine.update,导致引擎被多次重复更新,速度自然越来越快。
修复方案:
- 维护一个全局数组,存储所有需要渲染的下落文本对象
- 只保留一个全局渲染循环,统一处理引擎更新和所有下落对象的渲染
- 移除
explodeMe里的局部循环和重复的引擎更新
修复后的完整代码
HTML(无改动)
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.20.0/matter.min.js"></script> <div> <div id="physicscanvas"> <div id="ground"></div> </div> <p>When <span onclick="explodeMe(this)">this</span> text is clicked, it drops! Likewise, <span onclick="explodeMe(this)">text over here</span> drops too.</p> </div>
CSS(无改动)
.fallingtext { position: absolute; z-index: 50; color: blue; background-color: #0f011f; text-align: center; } #physicscanvas { position: fixed; bottom: 0; margin: auto; width: 800px; height: 2500px; z-index: -5; opacity: 1; } html, body { position: relative; height: 100%; margin: 0; }
JavaScript(关键修改)
const engine = Matter.Engine.create(); const physicscanvas = document.getElementById("physicscanvas"); // 新增全局数组,管理所有下落文本对象 const fallingObjects = []; const ground = Matter.Bodies.rectangle( 200, 2560, 2000, 120, { isStatic: true } ); Matter.Composite.add(engine.world, [ground]); // 全局唯一渲染循环:统一更新引擎 + 渲染所有下落对象 (function rerender() { Matter.Engine.update(engine); // 遍历数组,调用每个下落对象的渲染方法 fallingObjects.forEach(obj => obj.render()); requestAnimationFrame(rerender); })(); function explodeMe(textid) { const explodedName = textid.innerHTML; var x_of_physicscanvas = physicscanvas.getBoundingClientRect().left; var x_of_text = textid.getBoundingClientRect().left; var x_pos_bugged = x_of_text - x_of_physicscanvas; var y_of_physicscanvas = physicscanvas.getBoundingClientRect().top; var y_of_text = textid.getBoundingClientRect().top; var y_pos = y_of_text - y_of_physicscanvas; textid.style.visibility = "hidden"; const fallingContainer = document.createElement("div"); fallingContainer.innerHTML = explodedName; fallingContainer.classList.add("fallingtext"); physicscanvas.appendChild(fallingContainer); var container_width = fallingContainer.offsetWidth; var container_height = fallingContainer.offsetHeight; x_pos = x_pos_bugged + (container_width / 2); var box = { w: container_width, h: container_height, body: Matter.Bodies.rectangle(x_pos, y_pos, container_width, container_height, { restitution: 0.7 }), elem: fallingContainer, render() { const { x, y } = this.body.position; this.elem.style.top = `${y - this.h / 2}px`; this.elem.style.left = `${x - this.w / 2}px`; this.elem.style.transform = `rotate(${this.body.angle}rad)`; }, }; Matter.Composite.add(engine.world, [box.body]); // 将新创建的下落对象加入全局数组 fallingObjects.push(box); // 移除原局部渲染循环和重复的引擎更新 return; }
关键改动说明:
- 新增
fallingObjects数组,统一管理所有需要渲染的文本对象 - 全局
rerender循环中,除了更新物理引擎,还遍历数组调用每个对象的render方法 - 删除
explodeMe函数内的局部渲染循环和重复的Matter.Engine.update调用,避免循环叠加和引擎重复更新
这样不管点击多少次,始终只有一个渲染循环在工作,引擎每秒只更新一次(和屏幕帧率同步),就不会出现速度翻倍的问题了。
内容的提问来源于stack exchange,提问作者itsolie
相关产品推荐
相关产品推荐

