Attach a Constraint to a Specific Point in Matter.js

In Matter.js, constraints connect physics bodies together or pin them to the environment. While constraints connect to the center of mass by default, you can target specific locations on a body using local offset vectors via the pointA and pointB properties. This guide demonstrates how to configure these relative coordinates, distinguish between local offsets and world coordinates, and assemble realistic mechanical connections like hinges and pivots.

Understanding Constraint Points

When defining a constraint with Matter.Constraint.create(), two primary concepts dictate where the attachment sits:

  1. Relative Offsets (Body Assigned): When a body is assigned to bodyA or bodyB, the corresponding pointA or pointB represents a relative offset from that body's center of mass (body.position).
  2. Absolute Coordinates (No Body Assigned): When bodyA or bodyB is omitted (or set to null), the corresponding point is treated as an absolute coordinate in world space.

Code Example: Offsetting from the Center

To attach a constraint away from the center of a body, supply the pixel offset along the X and Y axes:

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

// Create a body
const box = Bodies.rectangle(400, 300, 100, 40);

// Pin the top-left corner of the box to a fixed world position
const hinge = Constraint.create({
    pointA: { x: 400, y: 200 }, // Absolute world position
    bodyB: box,
    pointB: { x: -50, y: -20 }, // Local offset (top-left corner of the box)
    stiffness: 0.9,
    length: 50
});

// Add both to the physics world
Composite.add(engine.world, [box, hinge]);

Calculating Local Offsets

Because local points are relative to the center of mass, calculate edge and corner offsets using the body's dimensions:

For circles, offset using radial values (such as { x: radius, y: 0 } for the rightmost edge).

Connecting Two Bodies at Specific Points

To create linkages, chains, or ragdoll joints, attach constraints to specific offsets on both bodies simultaneously:

const bodyA = Bodies.rectangle(200, 200, 80, 20);
const bodyB = Bodies.rectangle(280, 200, 80, 20);

const joint = Constraint.create({
    bodyA: bodyA,
    pointA: { x: 40, y: 0 },  // Right edge of bodyA
    bodyB: bodyB,
    pointB: { x: -40, y: 0 }, // Left edge of bodyB
    length: 0,                // 0 length creates a direct hinge/pivot
    stiffness: 1
});

Composite.add(engine.world, [bodyA, bodyB, joint]);

Setting length: 0 locks the two specified attachment points together, allowing the bodies to rotate around that exact junction.