UNPKG

@liammartens/svg-path-properties

Version:

Calculate the length for an SVG path, to use it with node or a Canvas element

56 lines (49 loc) 1.58 kB
import { pathOrders } from "./types"; const length: { [key in pathOrders]: number } = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 }; const segmentRegExp = /([astvzqmhlc])([^astvzqmhlc]*)/gi; const numberRegExp = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/gi; export default (path: string) => { const segments = (path && path.length > 0 ? path : "M0,0").match(segmentRegExp); if (!segments) { throw new Error(`No path elements found in string ${path}`); } return segments.reduce((segmentsArray: [string, ...Array<number>][], segmentString: string) => { let command = segmentString.charAt(0); let type: pathOrders = command.toLowerCase() as pathOrders; const args = parseValues(segmentString.substr(1)); // overloaded moveTo if (type === "m" && args.length > 2) { segmentsArray.push([command, ...args.splice(0, 2)]); type = "l"; command = command === "m" ? "l" : "L"; } while (args.length >= 0) { if (args.length === length[type]) { segmentsArray.push([command, ...args.splice(0, length[type])]); break; } if (args.length < length[type]) { throw new Error( `Malformed path data: "${command}" must have ${length[type]} elements and has ${args.length}: ${segmentString}` ); } segmentsArray.push([command, ...args.splice(0, length[type])]); } return segmentsArray; }, []); }; const parseValues = (args: string) => { const numbers = args.match(numberRegExp); return numbers ? numbers.map(Number) : []; };