How to Lock X or Y Axis in Matter.js

Matter.js does not include a native property like lockAxisX or lockAxisY to freeze a single translation axis while keeping the other dynamic. However, you can lock a body’s movement to either the X or Y axis using engine lifecycle events or physical constraints. This guide explains how to restrict linear movement along a single axis efficiently without breaking the physics simulation.

The most reliable way to lock an axis is to update the engine's event loop. By listening to the beforeUpdate event, you can zero out the velocity and reset the position of the locked axis before collision resolution and movement integration occur.

Locking the X-Axis (Vertical-Only Movement)

To allow a body to move freely up and down (Y-axis) while preventing any side-to-side motion (X-axis):

const initialX = body.position.x;

Matter.Events.on(engine, 'beforeUpdate', () => {
    // Reset the position on the X axis to its initial anchor
    Matter.Body.setPosition(body, {
        x: initialX,
        y: body.position.y
    });

    // Zero out velocity along the X axis
    Matter.Body.setVelocity(body, {
        x: 0,
        y: body.velocity.y
    });
});

Locking the Y-Axis (Horizontal-Only Movement)

To allow a body to slide left and right (X-axis) while preventing falling or jumping (Y-axis):

const initialY = body.position.y;

Matter.Events.on(engine, 'beforeUpdate', () => {
    // Reset the position on the Y axis to its initial anchor
    Matter.Body.setPosition(body, {
        x: body.position.x,
        y: initialY
    });

    // Zero out velocity along the Y axis
    Matter.Body.setVelocity(body, {
        x: body.velocity.x,
        y: 0
    });
});

Using Matter.Body.setPosition and Matter.Body.setVelocity ensures that internal momentum, previous positions, and collision forces do not cause drift or visual jitter.


Method 2: Using Matter.Constraint

Another approach is to attach the body to a fixed point or a slider using a constraint. While physical constraints simulate real-world joints, they are subject to stiffness parameters and may stretch under heavy forces.

To constrain a body to a fixed vertical line, you can anchor it using two rigid constraints:

const constraint = Matter.Constraint.create({
    pointA: { x: body.position.x, y: 0 },
    bodyB: body,
    pointB: { x: 0, y: 0 },
    stiffness: 1,
    length: 0
});

Matter.Composite.add(world, constraint);

While functional, constraints require tuning and can introduce instability under extreme forces. For strict axis locking, the beforeUpdate method remains the superior choice.


Locking Rotation Alongside Translation

Often, locking an axis requires locking rotation as well so the body acts like an elevator or sliding piston. Unlike translational axes, Matter.js natively supports locking rotation by setting inertia to Infinity:

const body = Matter.Bodies.rectangle(x, y, width, height, {
    inertia: Infinity // Completely locks rotation
});

Combining inertia: Infinity with the beforeUpdate velocity and position overrides gives you full control over single-axis linear motion.