How to Create Matter.js Bodies from SVG Paths
Generating a Matter.js physics body from an SVG path allows developers to build complex, custom rigid bodies beyond simple primitives like circles and rectangles. This article provides a concise, step-by-step guide explaining how to convert vector paths into physics vertices, decompose non-convex shapes using external helper libraries, and instantiate a functional rigid body inside the Matter.js physics simulation.
1. Install and Load Required Dependencies
Matter.js requires external libraries to parse complex SVG paths and handle concave polygons. Before generating bodies, you must include:
- Matter.js: The core 2D physics engine.
- poly-decomp.js: Matter.js uses this library
internally to decompose concave polygons into convex parts. Make sure
poly-decompis loaded before Matter.js or explicitly assigned towindow.decomp. - pathseg.js Polyfill: Modern browsers have
deprecated the SVG
getPathSegListAPI, which Matter.js uses to sample points along an SVG path. A polyfill is necessary to avoid runtime errors during extraction.
<script src="https://cdn.jsdelivr.net/npm/pathseg@1.2.1/pathseg.js"></script>
<script src="https://cdn.jsdelivr.net/npm/poly-decomp@0.3.0/build/decomp.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/matter-js@0.19.0/build/matter.min.js"></script>2. Extract the SVG Path Element
Load or locate the SVG path inside the DOM. If your SVG is an
external file, fetch it via fetch() and parse it using
DOMParser. If it is already rendered in the HTML, target it
directly using a standard selector.
const pathElement = document.querySelector('#my-svg-path');Alternatively, you can dynamically create the element:
const pathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathElement.setAttribute('d', 'M 0 0 L 100 0 L 100 100 L 0 100 Z');3. Convert the Path to Vertices
Matter.js provides a built-in utility named
Matter.Svg.pathToVertices(). This method samples points
along the vector path and converts them into an array of 2D vertex
objects ({ x, y }).
// sampleLength determines the resolution/number of points (lower = higher fidelity, higher CPU cost)
const sampleLength = 15;
const vertices = Matter.Svg.pathToVertices(pathElement, sampleLength);4. Construct the Rigid Body
Pass the generated vertices to
Matter.Bodies.fromVertices(). This function relies on
poly-decomp to automatically split any concave shape into
convex sub-bodies, combining them into a single compound body.
const x = 400; // X position in the world
const y = 300; // Y position in the world
const body = Matter.Bodies.fromVertices(x, y, [vertices], {
isStatic: false,
render: {
fillStyle: '#2e86de',
strokeStyle: '#ffffff',
lineWidth: 1
}
}, true); // The final boolean flag enables vertex optimization5. Add the Body to the Simulation
Finally, add the instantiated body to your Matter.js engine's world composite.
Matter.Composite.add(engine.world, body);Key Considerations
- Center of Mass: When using
Bodies.fromVertices(), Matter.js automatically recalculates the position relative to the shape's center of mass rather than the SVG's top-left coordinate origin. - Scaling: To resize the body, use
Matter.Body.scale(body, scaleX, scaleY)immediately after creation rather than attempting to manually modify raw vertex coordinates. - Holes and Self-Intersections: Matter.js does not support SVG paths containing internal cutouts (donut holes) or self-intersecting lines directly. Complex shapes with holes must be manually split into multiple adjoining paths.