How to Scale a Body Dynamically in Matter.js
Matter.js fully supports dynamically scaling rigid bodies at runtime
using its built-in physics methods. This article explains how to
dynamically resize bodies using the Matter.Body.scale
function, provides a direct code example for real-time scaling, and
highlights essential considerations regarding mass recalculation,
physics stability, and visual rendering.
Using the Body.scale
Method
To scale a body dynamically, use the static method
Matter.Body.scale(body, scaleX, scaleY, [point]). Rather
than setting an absolute size, this function applies a relative
multiplier to the body's current dimensions, vertices, and physical
properties.
body: The targetMatter.Bodyinstance you want to resize.scaleX: The horizontal scaling factor (e.g.,1.1increases width by 10%,0.9decreases it by 10%).scaleY: The vertical scaling factor.point(optional): The origin point from which scaling occurs. By default, it scales around the body's current center of mass (body.position).
Code Example: Dynamic Scaling
The following example demonstrates scaling an existing body over time within the engine's update cycle:
const { Engine, Render, Runner, Bodies, Composite, Body, Events } = Matter;
// Create engine and world
const engine = Engine.create();
const world = engine.world;
// Create a renderer
const render = Render.create({
element: document.body,
engine: engine,
options: { width: 800, height: 600, wireframes: false }
});
Render.run(render);
const runner = Runner.create();
Runner.run(runner, engine);
// Add a dynamic body
const box = Bodies.rectangle(400, 200, 80, 80);
Composite.add(world, box);
// Scale dynamically on every tick
let growing = true;
Events.on(engine, 'beforeUpdate', () => {
const scaleFactor = growing ? 1.01 : 0.99;
// Apply the scale to the body
Body.scale(box, scaleFactor, scaleFactor);
// Toggle growth bounds based on mass or area
if (box.area > 20000) growing = false;
if (box.area < 3000) growing = true;
});Critical Considerations
1. Automatic Mass and Inertia Updates
When Body.scale() is invoked, Matter.js automatically
recalculates the body's vertices, area, mass, and moment of inertia
based on its existing density. If you require the body's mass to remain
constant despite changing volume, manually reassign
box.mass or adjust box.density immediately
after scaling:
Body.scale(body, scaleX, scaleY);
Body.setMass(body, originalMass);2. Collision and Tunneling Issues
Scaling a body too rapidly can cause its boundaries to expand directly into neighboring bodies. Because physics engines resolve penetrations with explosive separation impulses, sudden large scale changes can launch overlapping objects across the screen. To prevent physics glitches, scale objects gradually across multiple frames.
3. Compound Bodies
If you scale a compound body (a body formed by multiple parts),
Body.scale() handles all child parts automatically,
adjusting their relative positions and shapes relative to the primary
center.
4. Custom Visual Synchronization
If you use a custom rendering pipeline (such as HTML5 Canvas, PixiJS,
or Three.js) instead of the default Matter.js Render
module, note that Body.scale modifies the body's vertex
positions directly. You must update your visual sprite dimensions or
scale matrices to match the updated physics bounds.