Skip to content

运行示例窗口

示例窗口提示

  • 红色按钮恢复原始状态
  • 黄色按钮缩小/恢复
  • 绿色按钮开启画中画
  • 可通过标题栏拖动窗口。
  • 可拖动窗口右下角改变窗口大小。
  • 可通过清除按钮清除世界内的所有物体。

窗口

开始

安装

bash
npm install matter-js
html
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>

示例

  1. 创建引擎
  2. 创建渲染器,将引擎和画布关联起来
  3. 创建物体
  4. 添加物体到世界
  5. 运行世界
javascript
// class MatterJsExample
this.Engine = Matter.Engine;    // 引擎
this.Render = Matter.Render;    // 渲染器
this.Runner = Matter.Runner;    // 运行器
this.Bodies = Matter.Bodies;    // 物体
this.Composite = Matter.Composite;  // 组合

// 创建一个引擎
this.engine = this.Engine.create();

// 创建一个渲染器
this.render = this.Render.create({
    element: document.querySelector("#matter-js-canvas"),   // 指定渲染的元素
    engine: this.engine,    // 指定引擎
    options: {
        width: 600,          // 设置画布宽
        height: 600,         // 设置画布高
        wireframes: false,   // 关闭线框模式
    }
});

let boxA = this.Bodies.rectangle(40, 40, 80, 80);  // 矩形
this.Composite.add(this.engine.world, boxA);


// 运行渲染器
this.Render.run(this.render);

// 创建一个 runner
this.runner = this.Runner.create();

// 运行引擎
this.Runner.run(this.runner, this.engine);

创造物体

矩形(rectangle)

xy为矩形中心点,widthheight是矩形的宽高,options为物体的属性配置,在后面会详细介绍。

javascript
this.Bodies.rectangle(x, y, width, height, options);

x

y

width

height

options

圆形(circle)

xy是圆心坐标,radius是半径,options为物体的属性配置,在后面会详细介绍。

javascript
this.Bodies.circle(x, y, radius, options);

x

y

radius

options

梯形(trapezoid)

xy定义了梯形的中心点坐标,widthheight是梯形的宽高,slope是斜率,options为物体的属性配置,在后面会详细介绍。

javascript
this.Bodies.trapezoid(x, y, width, height, slope, options);

x

y

width

height

slope

options

多边形(polygon)

xy定义了梯形的中心点坐标,sides是多边形的边数,radius是多边形的半径,options为物体的属性配置,在后面会详细介绍。

javascript
this.Bodies.polygon(x, y, sides, radius, options);

x

y

sides

radius

options

由顶点绘制图形(fromVertices)

xy定义了图形的中心点坐标,vertexSets是顶点集合,如[{ x: 0, y: 0 }, { x: 20, y: 0 },{ x: 70, y: 80 }, { x: 30, y: 80 }]options为物体的属性配置,在后面会详细介绍。

javascript
this.Bodies.fromVertices(x, y, vertexSets, options);

x

y

vertexSets

options

物体属性配置

填充颜色

render.fillStyle为填充颜色,render.strokeStyle为边框颜色,render.lineWidth为边框宽度。

javascript
this.Bodies.rectangle(40, 40, 80, 80, {
    render: {
        fillStyle: '#FFFFFF',   // 填充颜色
        strokeStyle: '#FF0000', // 边框颜色
        lineWidth: 4            // 边框宽度
    }
});

纹理

render.sprite为纹理配置,texture是纹理图片路径,xScaleyScale是纹理图片的缩放比例,xOffsetyOffset是纹理图片的偏移量。

javascript
this.Bodies.rectangle(300, 300, 128, 128, {
    render: {
        sprite: {
            texture: './img/fill.png',
            xScale: 0.25,
            yScale: 0.25,
            xOffset: 0,
            yOffset: 0
        }
    }
});

透明度

render.opacity为物体的透明度。

javascript
this.Bodies.rectangle(300, 300, 128, 128, {
    render: {
        opacity: 0.1
    }
});

是否显示

render.visible为物体是否显示。

javascript

this.Bodies.rectangle(300, 300, 128, 128, {
    render: {
        visible: false
    }
});

旋转

angle为旋转角度。

javascript
this.Bodies.rectangle(300, 300, 100, 100, {
    angle: Math.PI / 180 * 45
});

静止

isStatic可以设置物体是否静止。

javascript
let ground = this.Bodies.rectangle(300, 590, 600, 20, {
    isStatic: true,
    render: {
        fillStyle: '#FFFFFF'
    }
});

空气阻力

frictionAir可以设置物体的空气阻力。

javascript
let boxH = this.Bodies.rectangle(300, 300, 100, 100, {
    frictionAir: 0.01
});

摩擦力

friction可以设置物体的摩擦力。

javascript
let boxH = this.Bodies.rectangle(300, 300, 100, 100, {
    friction: 1
});

弹力

restitution可以设置物体的弹力。

javascript
this.Bodies.rectangle(300, 300, 100, 100, {
    restitution: 2
});

质量

mass可以设置物体的质量。

javascript
this.Bodies.rectangle(300, 300, 100, 100, {
    mass: 100
});

xxyy为堆的起始位置,columnsrows为堆的列数和行数,columnGaprowGap为堆的列间距和行间距,callback为堆中每个物体的回调函数。

javascript
Matter.Composites.stack(xx, yy, columns, rows, columnGap, rowGap, callback)

示例

javascript
Matter.Composites.stack(100, 100, 3, 3, 10, 10, (x, y) => {
    return this.Bodies.rectangle(x, y, 50, 50, {
        restitution: 0.8,
        mass: 0.5
    });
});

约束

示例一

javascript
let bodyA = this.Bodies.rectangle(310, 530, 20, 100, {
    isStatic: true,
    render: {
        fillStyle: '#f00'
    },
    collisionFilter: {
        group: -1
    }
});
let bodyB = this.Bodies.rectangle(340, 530, 550, 10, {
    render: {
        fillStyle: '#00f'
    },
    collisionFilter: {
        group: -1
    }
});
let rotateConstraint = Matter.Constraint.create({
    bodyA: bodyA,
    bodyB: bodyB,
    length: 0
})

let stack_boxA = Matter.Composites.stack(10, 30, 4, 3, 10, 20, function (x, y) {
    return Matter.Bodies.rectangle(x, y, 40, 20)
});
let stack_boxB = Matter.Composites.stack(320, 30, 3, 4, 10, 20, function (x, y) {
    return Matter.Bodies.rectangle(x, y, 40, 20)
});
let ground = this.Bodies.rectangle(300, 590, 600, 20, {
    isStatic: true,
    render: {
        fillStyle: '#FFFFFF'
    }
});

this.add([bodyA, bodyB, rotateConstraint, stack_boxA, stack_boxB, ground])

示例二

javascript
let circleA = this.Bodies.circle(400, 100, 20, {
    isStatic: true
});
let circleB = this.Bodies.circle(400, 300, 20);
let spring = Matter.Constraint.create({
    bodyA: circleA,
    bodyB: circleB,
    pointA: Matter.Vector.create(0, 0),
    pointB: Matter.Vector.create(0, 0),
    length: 100,
    stiffness: 0.1,
    damping: 0.1
});
this.add([circleA, circleB, spring]);

Matter.Constraint.create(options)的配置对象包含以下属性:

  • bodyA:类型为Matter.Body,约束连接的第一个物体。
  • pointA:类型为Matter.Vector,约束连接的第一个物体上的点。
  • bodyB:类型为Matter.Body,约束连接的第二个物体。
  • pointB:类型为Matter.Vector,约束连接的第二个物体上的点。
  • length:类型为number,约束的初始长度。
  • stiffness:类型为number,约束的刚度系数。
  • damping:类型为number,约束的阻尼系数。
  • render:约束的渲染选项。
  • render.visible:类型为boolean,表示约束是否可见,默认为 true。
  • render.lineWidth:类型为number,表示约束线条的宽度。
  • render.strokeStyle:类型为string,表示约束线条的颜色。

鼠标约束

javascript
let mouse = Matter.Mouse.create(this.render.canvas);
// 添加鼠标约束
let mouseConstraint = Matter.MouseConstraint.create(this.engine, {
    mouse: mouse,
    constraint: {
        render: {
            visible: false // 默认为 true,会显示鼠标拖拽轨迹
        }
    }
});
this.add(mouseConstraint);

引擎

重力

engine.gravity可以改变重力向量。scale可以改变重力大小,xy可以改变重力方向。

javascript
this.engine.gravity.scale = 0.001;
this.engine.gravity.y = -1;
this.engine.gravity.x = 0;

x

y

scale

时间

engine.timing.timeScale可以设置时间缩放。

javascript
this.engine.timing.timeScale = 1;

timeScale

事件监听

鼠标事件

javascript
// 监听鼠标按下事件
Matter.Events.on(mouseConstraint, 'mousedown', function(event) {
  console.log('按下')
})

// 监听鼠标移动事件
Matter.Events.on(mouseConstraint, "mousemove", function(event) {
  console.log('移动')
})

// 监听鼠标抬起事件
Matter.Events.on(mouseConstraint, "mouseup", function(event) {
  console.log('抬起')
})

// 监听鼠标拖拽刚体 - 开始拖拽
Matter.Events.on(mouseConstraint, 'startdrag', function(event) {
  console.log('开始拖拽')
})

// 监听鼠标拖拽刚体 - 结束拖拽
Matter.Events.on(mouseConstraint, 'enddrag', function(event) {
  console.log('结束拖拽')
})

碰撞事件

javascript
// 碰撞开始事件
Matter.Events.on(this.engine, 'collisionStart', function(event) {
    console.log('碰撞开始', event)
});
// 碰撞持续事件
Matter.Events.on(this.engine, 'collisionActive', function(event) {
    console.log('碰撞', event)
});
// 碰撞结束事件
Matter.Events.on(this.engine, 'collisionEnd', function(event) {
    console.log('碰撞结束', event)
});

渲染事件

javascript
Matter.Events.on(this.render, 'beforeRender', function() {
    console.log('渲染前')
});
Matter.Events.on(this.render, 'afterRender', function() {
    console.log('渲染后')
});

更新事件

javascript
Matter.Events.on(this.engine, 'beforeUpdate', function() {
    console.log('更新前')
});
Matter.Events.on(this.engine, 'afterUpdate', function() {
    console.log('更新后')
});

一些例子

弹弓

javascript
let ground = this.Bodies.rectangle(300, 590, 600, 20, { isStatic: true, render: { fillStyle: '#FFFFFF' } });
let rockOptions = {
    frictionAir: 0.001
};
let rock = this.Bodies.circle(150, 450, 25, rockOptions);
let tempRock = this.Bodies.circle(150, 450, 1, {
    isStatic: true,
    render: { visible: false },
    collisionFilter: {
        mask: 0x0000
    }
});
let anchor = { x: 150, y: 450 }
let elastic = Matter.Constraint.create({
    pointA: anchor,
    bodyB: rock,
    pointB: { x: 0, y: 0 },
    length: 0.1,
    damping: 0.01,
    stiffness: 0.05
});

this.add([ground, rock, elastic])

let mouse = Matter.Mouse.create(this.render.canvas);
let mouseConstraint = Matter.MouseConstraint.create(this.engine, {
    mouse: mouse,
    constraint: {
        stiffness: 0.2,
        render: {
            visible: false
        }
    }
});
this.add(mouseConstraint);

Matter.Events.on(this.engine, 'afterUpdate', () => {
    if (mouseConstraint.mouse.button === -1 && (rock.position.x > 190 || rock.position.y < 430) && elastic.bodyB === rock) {
        if (Matter.Body.getSpeed(rock) > 45) {
            Matter.Body.setSpeed(rock, 45);
        }
        elastic.bodyB = tempRock;
        setTimeout(() => {
            rock = this.Bodies.circle(150, 450, 25, rockOptions);
            this.add(rock);
            elastic.bodyB = rock;
        }, 1000);
    }
})

文字

javascript
let canvas = document.createElement('canvas');
canvas.width = 120;
canvas.height = 50;
let ctx = canvas.getContext('2d');
ctx.fillStyle = '#fff';
ctx.font = '50px Arial';
ctx.textAlign = 'left';
ctx.fillText('Hello', 0, 50);
let dataurl = canvas.toDataURL("image/png");
let text = this.Bodies.rectangle(300, 300, 120, 50, {
    render: {
        sprite: {
            texture: dataurl,
            xScale: 1,
            yScale: 1,
            xOffset: 0,
            yOffset: 0
        }
    }
});
this.add(text);