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