Prevent MouseConstraint from Grabbing Static Bodies

When building interactive simulations with Matter.js, you often want users to drag dynamic objects while leaving scenery, boundaries, and walls undisturbed. By default, mouse interactions can target or attempt to interact with static bodies unless configured otherwise. This article outlines the two most effective methods to prevent a MouseConstraint from grabbing or targeting static bodies: using collision filters and listening to the startdrag event.

The most robust and performant way to restrict what a MouseConstraint can touch is by using Matter.js collision categories and masks. By assigning static bodies to a separate category, you can explicitly tell the mouse constraint to ignore them.

const defaultCategory = 0x0001; // Dynamic objects
const staticCategory = 0x0002;  // Walls, floors, and platforms

// 1. Assign the static category to your static body
const wall = Matter.Bodies.rectangle(400, 600, 800, 50, {
    isStatic: true,
    collisionFilter: {
        category: staticCategory
    }
});

// 2. Assign the default category to dynamic bodies
const box = Matter.Bodies.rectangle(400, 200, 80, 80, {
    collisionFilter: {
        category: defaultCategory
    }
});

// 3. Configure the MouseConstraint mask to only interact with dynamic bodies
const mouse = Matter.Mouse.create(render.canvas);
const mouseConstraint = Matter.MouseConstraint.create(engine, {
    mouse: mouse,
    collisionFilter: {
        mask: defaultCategory // Only interacts with bodies having defaultCategory
    }
});

Matter.Composite.add(world, [wall, box, mouseConstraint]);

By setting collisionFilter.mask to only match defaultCategory, the MouseConstraint queries will completely bypass any body assigned to staticCategory.

Method 2: Canceling Drag on the startdrag Event

If you prefer not to manage collision categories across your entire simulation, you can intercept the drag event. Matter.js emits a startdrag event whenever a body is clicked. You can check if the targeted body is static and cancel the constraint immediately.

const mouse = Matter.Mouse.create(render.canvas);
const mouseConstraint = Matter.MouseConstraint.create(engine, {
    mouse: mouse
});

// Intercept drag initialization
Matter.Events.on(mouseConstraint, 'startdrag', function(event) {
    if (event.body.isStatic) {
        // Clear the body references to cancel the grab
        mouseConstraint.body = null;
        mouseConstraint.constraint.bodyB = null;
    }
});

Matter.Composite.add(world, mouseConstraint);

Setting mouseConstraint.body and mouseConstraint.constraint.bodyB to null prevents the mouse spring from attaching to the static object, leaving it fully immobile.