How to Constrain a Body to a Fixed Point in Matter.js

Constraining a physics body to a fixed point in Matter.js allows you to create pendulums, pinned joints, hanging signs, and elastic tethers. This article explains how to use the Matter.Constraint module to pin any dynamic body to a static coordinate in world space by leaving one side of the constraint detached from any physical body.


The Mechanism: One-Ended Constraints

In Matter.js, constraints typically connect two bodies (bodyA and bodyB). However, if you omit bodyA (or set it to null), the coordinates defined in pointA will be treated as an absolute position in the world space (the canvas background), rather than an offset relative to a body.

Basic Implementation

To attach a body to a fixed background coordinate, use Constraint.create() with pointA set to the world coordinates and bodyB set to your moving body.

const { Engine, Render, Runner, Bodies, Composite, Constraint } = Matter;

// 1. Create engine and renderer
const engine = Engine.create();
const render = Render.create({
    element: document.body,
    engine: engine,
    options: { width: 800, height: 600, wireframes: false }
});

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

// 2. Create the dynamic body
const dynamicCircle = Bodies.circle(400, 300, 30, {
    density: 0.04
});

// 3. Create the constraint pinned to a fixed background point
const fixedConstraint = Constraint.create({
    pointA: { x: 400, y: 150 }, // Fixed point in the world
    bodyB: dynamicCircle,       // The moving body
    pointB: { x: 0, y: 0 },     // Offset from the center of bodyB
    stiffness: 1,               // 1 is completely rigid; lower values are springy
    length: 150                 // Distance between pointA and pointB
});

// 4. Add both to the world
Composite.add(engine.world, [dynamicCircle, fixedConstraint]);

Key Configuration Properties

Pinning a Body Directly in Place

If you want a body to rotate freely around a fixed point on itself (like a spinner or a wheel), match the pointA coordinates to the body's starting position and set length: 0:

const spinner = Bodies.rectangle(400, 300, 200, 20, { density: 0.001 });

const pivot = Constraint.create({
    pointA: { x: 400, y: 300 },
    bodyB: spinner,
    pointB: { x: 0, y: 0 },
    length: 0,
    stiffness: 1
});

Composite.add(engine.world, [spinner, pivot]);