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.
Method 1:
Using the beforeUpdate Event (Recommended)
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.