perf: tidy svg frame bg render pass

This commit is contained in:
Ryan Di
2026-03-18 19:38:53 +11:00
parent 2b3871856e
commit 8d003a1d21
+76 -54
View File
@@ -720,26 +720,15 @@ export const renderSceneToSvg = (
return; return;
} }
const renderedFrameBackgrounds = new Set<string>(); const nonIframeElements = elements.filter((el) => !isIframeLikeElement(el));
const maybeRenderFrameBackground = ( const frameBackgroundByElementId = new Map<
element: NonDeletedExcalidrawElement | ExcalidrawFrameLikeElement, ExcalidrawElement["id"],
) => { ExcalidrawFrameLikeElement
if ( >();
!renderConfig.frameRendering.enabled ||
(!renderConfig.frameRendering.outline && !renderConfig.exportingFrame)
) {
return;
}
const frame =
renderConfig.exportingFrame ||
(isFrameLikeElement(element)
? element
: getContainingFrame(element, elementsMap));
const renderFrameBackgroundNode = (frame: ExcalidrawFrameLikeElement) => {
if ( if (
!frame || !frame ||
renderedFrameBackgrounds.has(frame.id) ||
!frame.backgroundColor || !frame.backgroundColor ||
isTransparent(frame.backgroundColor) isTransparent(frame.backgroundColor)
) { ) {
@@ -777,58 +766,91 @@ export const renderSceneToSvg = (
rect.setAttribute("stroke", "none"); rect.setAttribute("stroke", "none");
svgRoot.appendChild(rect); svgRoot.appendChild(rect);
renderedFrameBackgrounds.add(frame.id);
}; };
if (renderConfig.exportingFrame) { if (
maybeRenderFrameBackground(renderConfig.exportingFrame); renderConfig.frameRendering.enabled &&
(renderConfig.frameRendering.outline || renderConfig.exportingFrame)
) {
const renderedFrameBackgrounds = new Set<string>();
if (renderConfig.exportingFrame) {
renderFrameBackgroundNode(renderConfig.exportingFrame);
renderedFrameBackgrounds.add(renderConfig.exportingFrame.id);
}
const maybeQueueFrameBackground = (
element: NonDeletedExcalidrawElement | ExcalidrawFrameLikeElement,
) => {
const frame = isFrameLikeElement(element)
? element
: getContainingFrame(element, elementsMap);
if (
!frame ||
renderedFrameBackgrounds.has(frame.id) ||
!frame.backgroundColor ||
isTransparent(frame.backgroundColor)
) {
return;
}
frameBackgroundByElementId.set(element.id, frame);
renderedFrameBackgrounds.add(frame.id);
};
nonIframeElements.forEach((element) => {
if (!element.isDeleted) {
maybeQueueFrameBackground(element);
}
});
} }
// render elements // render elements
elements nonIframeElements.forEach((element) => {
.filter((el) => !isIframeLikeElement(el)) if (!element.isDeleted) {
.forEach((element) => { const frameBackground = frameBackgroundByElementId.get(element.id);
if (!element.isDeleted) { if (frameBackground) {
maybeRenderFrameBackground(element); renderFrameBackgroundNode(frameBackground);
if ( }
isTextElement(element) && if (
element.containerId && isTextElement(element) &&
elementsMap.has(element.containerId) element.containerId &&
) { elementsMap.has(element.containerId)
// will be rendered with the container ) {
return; // will be rendered with the container
} return;
}
try { try {
renderElementToSvg(
element,
elementsMap,
rsvg,
svgRoot,
files,
element.x + renderConfig.offsetX,
element.y + renderConfig.offsetY,
renderConfig,
);
const boundTextElement = getBoundTextElement(element, elementsMap);
if (boundTextElement) {
renderElementToSvg( renderElementToSvg(
element, boundTextElement,
elementsMap, elementsMap,
rsvg, rsvg,
svgRoot, svgRoot,
files, files,
element.x + renderConfig.offsetX, boundTextElement.x + renderConfig.offsetX,
element.y + renderConfig.offsetY, boundTextElement.y + renderConfig.offsetY,
renderConfig, renderConfig,
); );
const boundTextElement = getBoundTextElement(element, elementsMap);
if (boundTextElement) {
renderElementToSvg(
boundTextElement,
elementsMap,
rsvg,
svgRoot,
files,
boundTextElement.x + renderConfig.offsetX,
boundTextElement.y + renderConfig.offsetY,
renderConfig,
);
}
} catch (error: any) {
console.error(error);
} }
} catch (error: any) {
console.error(error);
} }
}); }
});
// render embeddables on top // render embeddables on top
elements elements