Skip to content

Commit a8c75a8

Browse files
committed
Fix SVG z-order: move edges below nodes in exported SVG
1 parent 7e19873 commit a8c75a8

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

src/lib/export/svg/renderer.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,43 @@ function calculateBounds(container: HTMLElement, viewport: HTMLElement): Bounds
129129
return bounds;
130130
}
131131

132+
/**
133+
* Fix SVG z-order: move edge groups before node groups.
134+
* SvelteFlow layers nodes above edges via CSS z-index, but SVG uses
135+
* DOM order for paint order. Find the deepest group containing all
136+
* content and reorder so edges come first.
137+
*/
138+
function fixEdgeNodeOrder(svg: SVGSVGElement): void {
139+
// Find the viewport group (deepest group with multiple children)
140+
let group: Element = svg;
141+
while (true) {
142+
const gChildren = Array.from(group.children).filter(c => c.tagName === 'g');
143+
if (gChildren.length === 1) { group = gChildren[0]; continue; }
144+
break;
145+
}
146+
147+
// Partition children into edge groups and non-edge groups
148+
const children = Array.from(group.children);
149+
const edgeGroups: Element[] = [];
150+
const otherGroups: Element[] = [];
151+
152+
for (const child of children) {
153+
const hasEdge = child.querySelector('[aria-label^="Edge from"]');
154+
if (hasEdge) {
155+
edgeGroups.push(child);
156+
} else {
157+
otherGroups.push(child);
158+
}
159+
}
160+
161+
if (edgeGroups.length === 0) return;
162+
163+
// Reorder: edges first (painted below), then everything else (painted on top)
164+
for (const el of [...edgeGroups, ...otherGroups]) {
165+
group.appendChild(el);
166+
}
167+
}
168+
132169
export async function exportToSVG(options: ExportOptions = {}): Promise<string> {
133170
const opts: Required<ExportOptions> = { ...DEFAULT_OPTIONS, ...options };
134171
const padding = opts.padding;
@@ -191,6 +228,11 @@ export async function exportToSVG(options: ExportOptions = {}): Promise<string>
191228
result.svg.setAttribute('height', String(svgHeight));
192229
result.svg.setAttribute('viewBox', `0 0 ${svgWidth} ${svgHeight}`);
193230

231+
// Fix z-order: SvelteFlow uses CSS z-index to layer nodes above edges,
232+
// but SVG has no z-index — paint order is DOM order. Move edge groups
233+
// before node groups so nodes render on top.
234+
fixEdgeNodeOrder(result.svg);
235+
194236
return result.toString();
195237
} finally {
196238
// Restore everything

0 commit comments

Comments
 (0)