UNPKG

svg-pathdata

Version:

Manipulate SVG path data (path[d] attribute content) simply and efficiently.

121 lines (106 loc) 2.7 kB
import { SVGPathData } from './SVGPathData.js'; import type { SVGCommand } from './types.js'; function moveTo(x: number, y: number): SVGCommand { return { type: SVGPathData.MOVE_TO, relative: false, x, y }; } function lineTo(x: number, y: number): SVGCommand { return { type: SVGPathData.LINE_TO, relative: false, x, y }; } function arcTo( rx: number, ry: number, xRot: number, largeArc: 0 | 1, sweep: 0 | 1, x: number, y: number, ): SVGCommand { return { type: SVGPathData.ARC, relative: false, rX: rx, rY: ry, xRot, lArcFlag: largeArc, sweepFlag: sweep, x, y, }; } /** * Creates an ellipse path centered at (cx,cy) with radii rx and ry */ function createEllipse( rx: number, ry: number, cx: number, cy: number, ): SVGPathData { return new SVGPathData([ moveTo(cx + rx, cy), arcTo(rx, ry, 0, 1, 1, cx - rx, cy), arcTo(rx, ry, 0, 1, 1, cx + rx, cy), { type: SVGPathData.CLOSE_PATH }, ]); } /** * Creates a rectangle path with optional rounded corners */ function createRect( x: number, y: number, width: number, height: number, rX = 0, rY = 0, ): SVGPathData { if (rX === 0 || rY === 0) { return new SVGPathData([ moveTo(x, y), lineTo(x + width, y), lineTo(x + width, y + height), lineTo(x, y + height), { type: SVGPathData.CLOSE_PATH }, ]); } const rx = Math.min(rX, width / 2); const ry = Math.min(rY, height / 2); return new SVGPathData([ moveTo(x + rx, y), lineTo(x + width - rx, y), arcTo(rx, ry, 0, 0, 1, x + width, y + ry), lineTo(x + width, y + height - ry), arcTo(rx, ry, 0, 0, 1, x + width - rx, y + height), lineTo(x + rx, y + height), arcTo(rx, ry, 0, 0, 1, x, y + height - ry), lineTo(x, y + ry), arcTo(rx, ry, 0, 0, 1, x + rx, y), { type: SVGPathData.CLOSE_PATH }, ]); } /** * Creates a polyline from an array of coordinates [x1,y1,x2,y2,...] */ function createPolyline(coords: number[]): SVGPathData { if (coords.length < 2) return new SVGPathData([]); const commands: SVGCommand[] = [moveTo(coords[0], coords[1])]; for (let i = 2; i < coords.length; i += 2) { commands.push(lineTo(coords[i], coords[i + 1])); } return new SVGPathData(commands); } /** * Creates a closed polygon from an array of coordinates */ function createPolygon(coords: number[]): SVGPathData { if (coords.length < 2) return new SVGPathData([]); const commands = createPolyline(coords).commands; commands.push({ type: SVGPathData.CLOSE_PATH }); return new SVGPathData(commands); } export const SVGShapes = { createEllipse, createRect, createPolyline, createPolygon, };