How to Parse SVG to Bodies Using Matter.Svg
Matter.js includes a built-in Matter.Svg utility
designed to convert standard SVG vector paths into fully functional 2D
rigid physics bodies. This article covers the step-by-step process of
loading an SVG, extracting path elements, decomposing complex concave
paths using the required poly-decomp library, and
instantiating custom physics bodies inside your Matter.js world.
1. Install and Include poly-decomp
Matter.js relies on an external decomposition library to handle
concave polygons generated from SVG paths. Before parsing paths into
bodies, install and load poly-decomp.
In a browser environment:
<script src="https://cdn.jsdelivr.net/npm/poly-decomp@0.3.0/build/decomp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>In a Node.js or bundler environment:
import Matter from 'matter-js';
import decomp from 'poly-decomp';
// Provide poly-decomp to Matter.js globally
Matter.Common.setDecomp(decomp);2. Prepare the SVG Path
Matter.Svg.pathToVertices accepts an SVG
<path> DOM element. Ensure your SVG graphic is
converted into path commands (<path d="..." />)
rather than primitive shapes like <rect> or
<circle>.
<svg id="svg-container" style="display: none;">
<path id="star-path" d="M 50 0 L 65 35 L 100 35 L 72 57 L 82 91 L 50 70 L 18 91 L 28 57 L 0 35 L 35 35 Z"></path>
</svg>3. Parse Path Data to Vertices
Fetch the <path> node and pass it to
Matter.Svg.pathToVertices(). This function samples points
along the curve or line segments.
const pathElement = document.getElementById('star-path');
// sampleLength determines vertex resolution (lower values mean higher accuracy and more vertices)
const sampleLength = 15;
const vertices = Matter.Svg.pathToVertices(pathElement, sampleLength);4. Create the Rigid Body
Pass the generated vertices to
Matter.Bodies.fromVertices(). This method decomposes the
shape into a compound body composed of convex sub-parts.
const x = 400; // X position in the physics world
const y = 200; // Y position in the physics world
const svgBody = Matter.Bodies.fromVertices(x, y, vertices, {
isStatic: false,
friction: 0.1,
restitution: 0.6,
render: {
fillStyle: '#2e86de',
strokeStyle: '#ffffff',
lineWidth: 1
}
}, true);
// Add the body to your simulation
Matter.Composite.add(engine.world, svgBody);5. Loading External SVG Files
To load external .svg files dynamically, fetch the file,
parse the response into a DOM document using DOMParser, and
then extract the vertices.
async function createBodyFromExternalSvg(url, x, y) {
const response = await fetch(url);
const svgText = await response.text();
const parser = new DOMParser();
const svgDoc = parser.parseFromString(svgText, 'image/svg+xml');
const pathElements = svgDoc.querySelectorAll('path');
const vertexSets = Array.from(pathElements).map(path =>
Matter.Svg.pathToVertices(path, 15)
);
const body = Matter.Bodies.fromVertices(x, y, vertexSets, {
restitution: 0.5
});
Matter.Composite.add(engine.world, body);
return body;
}Key Considerations
- Path Quality: Ensure paths are closed
(
Zcommand at the end) to avoid broken collision geometry. - Sample Resolution: Lower
sampleLengthvalues produce more accurate boundaries for curved lines but increase physics calculation overhead. A value between10and25provides a good balance between performance and accuracy. - Centering:
Matter.Bodies.fromVerticesautomatically recalculates the center of mass, shifting the visual origin relative to the path's original coordinates.