Parsing SVG Path Data into Arrays Using Regex
SVG path data stored in the d attribute uses a condensed
string format containing command letters and numerical coordinates. This
article explains how to parse raw SVG path strings into structured
mathematical arrays using regular expressions. By breaking down command
types, capturing numerical tokens with regex, and converting them into
numerical vectors, developers can extract coordinate matrices for
geometric processing, custom rendering, physics calculations, and canvas
animations.
Understanding SVG Path Data Syntax
An SVG path string consists of single-letter commands followed by coordinate parameters. For example:
M 10 20 L 30 40 C 50 60, 70 80, 90 100 Z
Parsing this data is challenging because the SVG specification allows
several compact formatting shortcuts: * Whitespace and commas between
numbers are optional if unambiguous (e.g., M10-20 means
M 10 -20). * Consecutive decimal points can omit leading
zeros and separators (e.g., L.5.5 means
L 0.5 0.5). * Numbers can use scientific notation (e.g.,
1e-4). * Subsequent coordinates after a command implicitly
repeat that command.
The Regular Expression Strategy
To parse the string into discrete mathematical units, the process is split into two regex operations: 1. Command Segment Matching: Splitting the path string into individual command letters along with their trailing parameter strings. 2. Number Tokenization: Extracting floating-point numbers, integers, and exponential values from each parameter string.
1. Extracting Command Blocks
The regex below matches any command character (M,
L, C, A, Z, etc.,
case-insensitive, excluding e which belongs to scientific
notation) followed by its associated coordinate string:
const COMMAND_REGEX = /([a-df-z])([^a-df-z]*)/gi;2. Extracting Coordinate Values
The number-parsing regex captures valid numerical values, including signs, decimals, and scientific notation:
const NUMBER_REGEX = /[-+]?(?:\d*\.\d+|\d+)(?:[eE][-+]?\d+)?/g;Implementation: Converting Path Data to Arrays
The following JavaScript function parses an SVG path string into an array of objects or multi-dimensional numerical arrays.
function parseSVGPathToArrays(pathData) {
const commandRegex = /([a-df-z])([^a-df-z]*)/gi;
const numberRegex = /[-+]?(?:\d*\.\d+|\d+)(?:[eE][-+]?\d+)?/g;
const parsedData = [];
let match;
while ((match = commandRegex.exec(pathData)) !== null) {
const command = match[1];
const rawNumbers = match[2].match(numberRegex);
const coordinates = rawNumbers ? rawNumbers.map(Number) : [];
parsedData.push({
command: command,
points: coordinates
});
}
return parsedData;
}Example Input and Output
Given the following input:
const path = "M0,0 L10.5,20.5 C30-40 50.2.8 100 200Z";
const result = parseSVGPathToArrays(path);The returned structured array will be:
[
{ command: "M", points: [0, 0] },
{ command: "L", points: [10.5, 20.5] },
{ command: "C", points: [30, -40, 50.2, 0.8, 100, 200] },
{ command: "Z", points: [] }
]Structuring into Coordinate Tuples
For mathematical calculations, flat parameter arrays can be grouped
into coordinate pairs ([x, y] vectors) based on the command
type:
function groupPoints(points, size = 2) {
const groups = [];
for (let i = 0; i < points.length; i += size) {
groups.push(points.slice(i, i + size));
}
return groups;
}
function normalizePathToMatrix(parsedData) {
return parsedData.map(item => {
switch (item.command.toUpperCase()) {
case 'M':
case 'L':
case 'T':
return { command: item.command, vectors: groupPoints(item.points, 2) };
case 'C':
return { command: item.command, vectors: groupPoints(item.points, 2) }; // Control points + endpoint
case 'Q':
case 'S':
return { command: item.command, vectors: groupPoints(item.points, 2) };
case 'H':
case 'V':
return { command: item.command, vectors: item.points.map(v => [v]) };
case 'A':
// Arcs contain 7 parameters: [rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y]
return { command: item.command, vectors: groupPoints(item.points, 7) };
case 'Z':
return { command: item.command, vectors: [] };
default:
return { command: item.command, vectors: groupPoints(item.points, 2) };
}
});
}Handling Implicit Repeated Commands
In the SVG specification, if a command letter is followed by more
coordinates than expected, the command repeats automatically: *
Subsequent points after M (MoveTo) are treated as implicit
L (LineTo) commands. * Subsequent points after other
commands (like C or L) repeat that same
command.
To handle this behavior, slice the extracted numbers according to the command’s parameter length and emit individual command arrays for each parameter set. This ensures consistent array dimensions for downstream linear algebra and transformation functions.