import { SVGPathData } from 'svg-pathdata' import arcToBezier from 'svg-arc-to-cubic-bezier' const typeMap = { 1: 'Z', 2: 'M', 4: 'H', 8: 'V', 16: 'L', 32: 'C', 64: 'S', 128: 'Q', 256: 'T', 512: 'A', } /** * 简单解析SVG路径 * @param d SVG path d属性 */ export const parseSvgPath = (d: string) => { const pathData = new SVGPathData(d) const ret = pathData.commands.map(item => { return { ...item, type: typeMap[item.type] } }) return ret } export type SvgPath = ReturnType /** * 解析SVG路径,并将圆弧(A)类型的路径转为三次贝塞尔(C)类型的路径 * @param d SVG path d属性 */ export const toPoints = (d: string) => { const pathData = new SVGPathData(d) const points = [] for (const item of pathData.commands) { const type = typeMap[item.type] if (item.type === 2 || item.type === 16) { points.push({ x: item.x, y: item.y, relative: item.relative, type, }) } if (item.type === 32) { points.push({ x: item.x, y: item.y, curve: { type: 'cubic', x1: item.x1, y1: item.y1, x2: item.x2, y2: item.y2, }, relative: item.relative, type, }) } else if (item.type === 128) { points.push({ x: item.x, y: item.y, curve: { type: 'quadratic', x1: item.x1, y1: item.y1, }, relative: item.relative, type, }) } else if (item.type === 512) { const lastPoint = points[points.length - 1] if (!['M', 'L', 'Q', 'C'].includes(lastPoint.type)) continue const cubicBezierPoints = arcToBezier({ px: lastPoint.x as number, py: lastPoint.y as number, cx: item.x, cy: item.y, rx: item.rX, ry: item.rY, xAxisRotation: item.xRot, largeArcFlag: item.lArcFlag, sweepFlag: item.sweepFlag, }) for (const cbPoint of cubicBezierPoints) { points.push({ x: cbPoint.x, y: cbPoint.y, curve: { type: 'cubic', x1: cbPoint.x1, y1: cbPoint.y1, x2: cbPoint.x2, y2: cbPoint.y2, }, relative: false, type: 'C', }) } } else if (item.type === 1) { points.push({ close: true, type }) } else continue } return points } export type SvgPoints = ReturnType