From 6483f3672378fdbf9011181b2f701ce97eca93d6 Mon Sep 17 00:00:00 2001 From: Yifeng Wang Date: Mon, 26 May 2025 01:06:46 +0800 Subject: [PATCH] refactor: use path builder --- .../element-renderer/connector-dom/index.ts | 70 +++++++++++++++++-- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/blocksuite/affine/gfx/connector/src/element-renderer/connector-dom/index.ts b/blocksuite/affine/gfx/connector/src/element-renderer/connector-dom/index.ts index 9f43ed1d4d..68dbc3f466 100644 --- a/blocksuite/affine/gfx/connector/src/element-renderer/connector-dom/index.ts +++ b/blocksuite/affine/gfx/connector/src/element-renderer/connector-dom/index.ts @@ -17,6 +17,60 @@ interface PathBounds { maxY: number; } +interface PathCommand { + command: string; + coordinates: number[]; +} + +class SVGPathBuilder { + private commands: PathCommand[] = []; + + moveTo(x: number, y: number): this { + this.commands.push({ + command: 'M', + coordinates: [x, y], + }); + return this; + } + + lineTo(x: number, y: number): this { + this.commands.push({ + command: 'L', + coordinates: [x, y], + }); + return this; + } + + curveTo( + cp1x: number, + cp1y: number, + cp2x: number, + cp2y: number, + x: number, + y: number + ): this { + this.commands.push({ + command: 'C', + coordinates: [cp1x, cp1y, cp2x, cp2y, x, y], + }); + return this; + } + + build(): string { + const pathSegments = this.commands.map(cmd => { + const coords = cmd.coordinates.join(' '); + return `${cmd.command} ${coords}`; + }); + + return pathSegments.join(' '); + } + + clear(): this { + this.commands = []; + return this; + } +} + function calculatePathBounds(path: PointLocation[]): PathBounds { if (path.length === 0) { return { minX: 0, minY: 0, maxX: 0, maxY: 0 }; @@ -43,23 +97,31 @@ function createConnectorPath( ): string { if (points.length < 2) return ''; - let pathData = `M ${points[0][0]} ${points[0][1]}`; + const pathBuilder = new SVGPathBuilder(); + pathBuilder.moveTo(points[0][0], points[0][1]); if (mode === ConnectorMode.Curve) { // Use bezier curves for (let i = 1; i < points.length; i++) { const prev = points[i - 1]; const curr = points[i]; - pathData += ` C ${prev.absOut[0]} ${prev.absOut[1]} ${curr.absIn[0]} ${curr.absIn[1]} ${curr[0]} ${curr[1]}`; + pathBuilder.curveTo( + prev.absOut[0], + prev.absOut[1], + curr.absIn[0], + curr.absIn[1], + curr[0], + curr[1] + ); } } else { // Use straight lines for (let i = 1; i < points.length; i++) { - pathData += ` L ${points[i][0]} ${points[i][1]}`; + pathBuilder.lineTo(points[i][0], points[i][1]); } } - return pathData; + return pathBuilder.build(); } function createArrowMarker(