| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- 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<typeof parseSvgPath>;
- /**
- * 解析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 const getSvgPathRange = (path: string) => {
- try {
- const pathData = new SVGPathData(path);
- const xList = [];
- const yList = [];
- for (const item of pathData.commands) {
- const x = 'x' in item ? item.x : 0;
- const y = 'y' in item ? item.y : 0;
- xList.push(x);
- yList.push(y);
- }
- return {
- minX: Math.min(...xList),
- minY: Math.min(...yList),
- maxX: Math.max(...xList),
- maxY: Math.max(...yList),
- };
- } catch {
- return {
- minX: 0,
- minY: 0,
- maxX: 0,
- maxY: 0,
- };
- }
- };
- export type SvgPoints = ReturnType<typeof toPoints>;
|