Detect Clicks on Matter.js Bodies Using MouseConstraint
This article explains how to detect user clicks on physics bodies in
Matter.js using the MouseConstraint module. By attaching
event listeners to the mouse constraint and checking for an active body
reference, you can reliably capture click events and execute custom
logic whenever a user interacts with an object in your 2D physics
scene.
Setting Up Mouse and MouseConstraint
To capture mouse interactions, Matter.js requires both a
Mouse instance and a MouseConstraint. The
Mouse tracks screen coordinates relative to the render
canvas, while the MouseConstraint connects mouse
interactions to the physics engine.
const { Engine, Render, Runner, Bodies, Composite, Mouse, MouseConstraint, Events } = Matter;
// Create engine and renderer
const engine = Engine.create();
const render = Render.create({
element: document.body,
engine: engine,
options: { width: 800, height: 600 }
});
// Create mouse and mouse constraint
const mouse = Mouse.create(render.canvas);
const mouseConstraint = MouseConstraint.create(engine, {
mouse: mouse,
constraint: {
stiffness: 0.2,
render: { visible: false }
}
});
Composite.add(engine.world, mouseConstraint);
render.mouse = mouse;Listening for Click Events
Matter.js provides an Events module to listen for
interactions on the MouseConstraint. The most direct way to
detect a click is by listening for the mousedown event on
the mouseConstraint instance.
When mousedown fires, inspect
mouseConstraint.body. If the mouse cursor is hovering over
a body when clicked, mouseConstraint.body will reference
that specific body; otherwise, it will be null.
Events.on(mouseConstraint, 'mousedown', function(event) {
const clickedBody = mouseConstraint.body;
if (clickedBody) {
console.log('Body clicked:', clickedBody);
// Execute custom logic here (e.g., change color, apply force, remove body)
}
});Differentiating Clicks from Drags
The mousedown event fires immediately upon pressing the
mouse button. If you need to detect a full click (a press followed by a
release) without triggering on drag gestures, track the mouse state
between mousedown and mouseup:
let targetBody = null;
Events.on(mouseConstraint, 'mousedown', function() {
targetBody = mouseConstraint.body;
});
Events.on(mouseConstraint, 'mouseup', function() {
if (targetBody && targetBody === mouseConstraint.body) {
console.log('Body clicked without dragging away:', targetBody);
}
targetBody = null;
});Filtering Specific Bodies
To limit interactions to specific entities, assign custom properties or labels to your bodies during creation, then evaluate those labels inside the event handler:
const interactiveBox = Bodies.rectangle(400, 200, 80, 80, {
label: 'clickableBox'
});
Composite.add(engine.world, interactiveBox);
Events.on(mouseConstraint, 'mousedown', function() {
const body = mouseConstraint.body;
if (body && body.label === 'clickableBox') {
// Specific logic for this body
Matter.Body.scale(body, 1.1, 1.1);
}
});Using mouseConstraint.body inside Matter.js
Events listeners provides a fast and efficient way to
handle clicks, raycasting, and user selections directly within your
simulation loop.