You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Matter.js时画布无内容显示,请求技术协助

Matter.js画布无内容显示问题排查与解决

问题描述

跟随Matter.js教程开发时,画布仅显示白色区域,无任何物理体内容,尝试过其他解决方案无效,以下是使用VS Code编写的HTML和JS代码:

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>square.</title>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script>
 <script src="scripts.js"></script>
 <style>
 canvas {
 position: relative;
 width: 800px;
 height: 600px;
 background-color: white;
 }
 </style>
</head>
<body onload='init()'>
 <div id="areaToRender">
 </div>
</body>
</html>

JS代码(原代码)

let Engine = Matter.Engine
    Render = Matter.Render
    Runner = Matter.Runner
    Bodies = Matter.Bodies
    Composite = Matter.Composite
    Composties = Matter. Composites
    Constraint = Matter.Constraint
    Mouse = Matter.Mouse 
let MouseConstraint = Matter.MouseConstraint
    Events = Matter.Events
let engine;
let render;
let runner;

function init() {
    engine = Engine.create();
}

render = Render.create({
    element: document.getElementById("areaToRender"),
    engine: engine,
    options: {
        width: 800,
        height: 600,
        pixelRatio: 1,
        background : '#fafafa',
        wireframes: false
    }
});

Render.run(render);
runner = Runner.create();
Runner.run(runner, engine);

let lastClear = "(not given)"
function clearWorld(exampleName) {
    if (lastClear != exampleName) {
        lastClear = exampleName

        Matter.Composite.clear(engine.world, false)
    }
}

function StartBoxes() {
    clearWorld("Boxes")
    let boxA = Bodies.rectangle(400, 200, 80, 80);
    let boxB = Bodies.rectangle(400, 200, 80, 80, {
        render: {
            fillStyle: 'red',
            strokeStyle: 'blue',
            lineWidth: 3
        }
    });

let ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true});

Composite.add(engine.world, [boxA, boxB, ground]);

Engine.update(engine);

}

问题根源与修复方案

  1. 核心问题:StartBoxes函数未被调用
    所有物理体的创建和添加逻辑都在StartBoxes函数中,但代码中没有任何触发该函数的逻辑,导致物理世界为空,画布自然无内容。

  2. 变量声明语法错误
    原代码中Composties = Matter. Composites和Mouse = Matter.Mouse 存在多余空格,会导致变量未正确绑定到Matter.js的对应模块,修正后:

    let Engine = Matter.Engine,
        Render = Matter.Render,
        Runner = Matter.Runner,
        Bodies = Matter.Bodies,
        Composite = Matter.Composite,
        Composites = Matter.Composites,
        Constraint = Matter.Constraint,
        Mouse = Matter.Mouse,
        MouseConstraint = Matter.MouseConstraint,
        Events = Matter.Events;
    
  3. 渲染代码执行时机错误
    原代码中Render.create、Render.run等逻辑在init函数外部执行,而engine是在body onload触发的init中才创建的,这会导致渲染器初始化时engine可能尚未完成创建,需将这些逻辑移到init函数内部。

  4. 画布尺寸配置冲突
    原HTML的CSS中设置canvas宽500px高400px,但Render选项中设置的是800x600,会导致画布缩放变形,已统一为800x600。

修正后的完整JS代码

let Engine = Matter.Engine,
    Render = Matter.Render,
    Runner = Matter.Runner,
    Bodies = Matter.Bodies,
    Composite = Matter.Composite,
    Composites = Matter.Composites,
    Constraint = Matter.Constraint,
    Mouse = Matter.Mouse,
    MouseConstraint = Matter.MouseConstraint,
    Events = Matter.Events;

let engine;
let render;
let runner;
let lastClear = "(not given)"

function init() {
    // 创建引擎
    engine = Engine.create();
    
    // 创建渲染器并绑定到指定元素
    render = Render.create({
        element: document.getElementById("areaToRender"),
        engine: engine,
        options: {
            width: 800,
            height: 600,
            pixelRatio: 1,
            background: '#fafafa',
            wireframes: false
        }
    });

    // 启动渲染器和运行器
    Render.run(render);
    runner = Runner.create();
    Runner.run(runner, engine);

    // 调用创建物理体的函数
    StartBoxes();
}

function clearWorld(exampleName) {
    if (lastClear !== exampleName) {
        lastClear = exampleName;
        Matter.Composite.clear(engine.world, false);
    }
}

function StartBoxes() {
    clearWorld("Boxes");
    let boxA = Bodies.rectangle(400, 200, 80, 80);
    let boxB = Bodies.rectangle(400, 200, 80, 80, {
        render: {
            fillStyle: 'red',
            strokeStyle: 'blue',
            lineWidth: 3
        }
    });

    let ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true});

    Composite.add(engine.world, [boxA, boxB, ground]);
}

验证效果

修正后,页面加载时init函数会自动执行,创建引擎、渲染器,并调用StartBoxes生成物理体,画布上会显示两个重叠的矩形(一个默认样式,一个红色填充蓝色边框)和底部的静态地面,物理体也会正常下落并与地面发生碰撞。

内容的提问来源于stack exchange,提问作者OverTheMoonAgain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:37:44