fix: stop font `loadingdone` loop when rendering element SVGs (#5883)

* fix: stop font `loadingdone` loop when rendering element SVGs

* update snaps

* stop updating scene elements array if no change was made

* always re-render if invalidating element shape
This commit is contained in:
David Luzar 2022-11-15 21:02:57 +01:00 committed by GitHub
parent d273acb7e4
commit bbe0c35f66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 52 additions and 17 deletions

View File

@ -730,18 +730,20 @@ class App extends React.Component<AppProps, AppState> {
}; };
private onFontLoaded = () => { private onFontLoaded = () => {
this.scene.replaceAllElements([ let didUpdate = false;
...this.scene.getElementsIncludingDeleted().map((element) => { this.scene.mapElements((element) => {
if (isTextElement(element)) { if (isTextElement(element)) {
invalidateShapeForElement(element); invalidateShapeForElement(element);
return newElementWith(element, { didUpdate = true;
...refreshTextDimensions(element), return newElementWith(element, {
}); ...refreshTextDimensions(element),
} });
return element; }
}), return element;
]); });
this.onSceneUpdated(); if (didUpdate) {
this.onSceneUpdated();
}
}; };
private resetHistory = () => { private resetHistory = () => {

View File

@ -44,6 +44,7 @@ export const LibraryUnit = ({
}, },
null, null,
); );
svg.querySelector(".style-fonts")?.remove();
node.innerHTML = svg.outerHTML; node.innerHTML = svg.outerHTML;
})(); })();

View File

@ -46,6 +46,7 @@ const ChartPreviewBtn = (props: {
}, },
null, // files null, // files
); );
svg.querySelector(".style-fonts")?.remove();
previewNode.replaceChildren(); previewNode.replaceChildren();
previewNode.appendChild(svg); previewNode.appendChild(svg);

View File

@ -79,6 +79,35 @@ class Scene {
return null; return null;
} }
/**
* A utility method to help with updating all scene elements, with the added
* performance optimization of not renewing the array if no change is made.
*
* Maps all current excalidraw elements, invoking the callback for each
* element. The callback should either return a new mapped element, or the
* original element if no changes are made. If no changes are made to any
* element, this results in a no-op. Otherwise, the newly mapped elements
* are set as the next scene's elements.
*
* @returns whether a change was made
*/
mapElements(
iteratee: (element: ExcalidrawElement) => ExcalidrawElement,
): boolean {
let didChange = false;
const newElements = this.elements.map((element) => {
const nextElement = iteratee(element);
if (nextElement !== element) {
didChange = true;
}
return nextElement;
});
if (didChange) {
this.replaceAllElements(newElements);
}
return didChange;
}
replaceAllElements(nextElements: readonly ExcalidrawElement[]) { replaceAllElements(nextElements: readonly ExcalidrawElement[]) {
this.elements = nextElements; this.elements = nextElements;
this.elementsMap.clear(); this.elementsMap.clear();

View File

@ -139,7 +139,7 @@ export const exportToSvg = async (
${SVG_EXPORT_TAG} ${SVG_EXPORT_TAG}
${metadata} ${metadata}
<defs> <defs>
<style> <style class="style-fonts">
@font-face { @font-face {
font-family: "Virgil"; font-family: "Virgil";
src: url("${assetPath}Virgil.woff2"); src: url("${assetPath}Virgil.woff2");

View File

@ -5,7 +5,7 @@ exports[`export exporting svg containing transformed images: svg export output 1
<!-- svg-source:excalidraw --> <!-- svg-source:excalidraw -->
<defs> <defs>
<style> <style class=\\"style-fonts\\">
@font-face { @font-face {
font-family: \\"Virgil\\"; font-family: \\"Virgil\\";
src: url(\\"https://excalidraw.com/Virgil.woff2\\"); src: url(\\"https://excalidraw.com/Virgil.woff2\\");

View File

@ -17,7 +17,9 @@ exports[`exportToSvg with default arguments 1`] = `
<defs> <defs>
<style> <style
class="style-fonts"
>
@font-face { @font-face {
font-family: "Virgil"; font-family: "Virgil";
@ -76,7 +78,7 @@ exports[`exportToSvg with elements that have a link 1`] = `
<!-- svg-source:excalidraw --> <!-- svg-source:excalidraw -->
<defs> <defs>
<style> <style class=\\"style-fonts\\">
@font-face { @font-face {
font-family: \\"Virgil\\"; font-family: \\"Virgil\\";
src: url(\\"https://excalidraw.com/Virgil.woff2\\"); src: url(\\"https://excalidraw.com/Virgil.woff2\\");
@ -95,7 +97,7 @@ exports[`exportToSvg with exportEmbedScene 1`] = `
<!-- svg-source:excalidraw --> <!-- svg-source:excalidraw -->
<!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1SPW/CMFx1MDAxMN35XHUwMDE1kbtcIpGk4aNstFRVpapcdTAwMWRcdTAwMTiQWnUw8YVYMbaxXHUwMDFkPoT477VccsRtxNpcclx1MDAwZpbu+b278907dKJcYpm9XHUwMDA0NI5cdTAwMTDscswoUXiLulx1MDAwZd+A0lRw+5T6WIta5Z5ZXHUwMDFhI8e9XHUwMDFlXHUwMDEzVlBcbm1OfGCwXHUwMDAybrRlfNk4ilx1MDAwZf62L5Q41Wau1lx1MDAxZpOiopyk63w1fJtOXj691JN2lpMlWVx1MDAxM+9d4fthXHUwMDEzbykxpcWSOG6wXHUwMDEy6LI0LVx1MDAxMPMlc21cdTAwMDZEXHUwMDFiJSp4XHUwMDEyTCjXyF3sTyi9wHm1VKLmJHCSPsaLXCJwXG7K2Mzs2WlcdTAwMDA4L2tcdTAwMDWoVWF+abGFNzot7ICDypZcXJZcdTAwMWO0/qNcdTAwMTFcdTAwMTLn1Oxbv3L9yVfip/vdzl9iJc95kHbBr85cdTAwMDCIT5Ulg/7wIVx1MDAxZTUvYb9JXHUwMDFht9F3wf2uk2Q0iuMsXHUwMDFkXHUwMDBlXHUwMDFhXHUwMDA21VO7auPTXHUwMDE2mGlcYnN0I3xcdTAwMGU24DVjzWMtXHQ+icJXXHUwMDE55VWbZ11VXcl9cSmheCU4QVx1MDAxZT92b0a7XHUwMDE57X+MXHUwMDA2jFGp4Ww0e/thICzlzNj8lnKyXHUwMDFk2lDYPl5ZbOGP03ubusWCa/Zw7Fx1MDAxY39cdTAwMDCLqmbvIn0=<!-- payload-end --> <!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1SPW/CMFx1MDAxMN35XHUwMDE1kbtcIpGk4aNstFRVpapcdTAwMWRcdTAwMTiQWnUw8YVYMbaxXHUwMDFkPoT477VccsRtxNpcclx1MDAwZpbu+b278907dKJcYpm9XHUwMDA0NI5cdTAwMTDscswoUXiLulx1MDAwZd+A0lRw+5T6WIta5Z5ZXHUwMDFhI8e9XHUwMDFlXHUwMDEzVlBcbm1OfGCwXHUwMDAybrRlfNk4ilx1MDAwZf62L5Q41Wau1lx1MDAxZpOiopyk63w1fJtOXj691JN2lpMlWVx1MDAxM+9d4fthXHUwMDEzbykxpcWSOG6wXHUwMDEy6LI0LVx1MDAxMPMlc21cdTAwMDZEXHUwMDFiJSp4XHUwMDEyTCjXyF3sTyi9wHm1VKLmJHCSPsaLXCJwXG7K2Mzs2WlcdTAwMDA4L2tcdTAwMDWoVWF+abGFNzot7ICDypZcXJZcdTAwMWO0/qNcdTAwMTFcdTAwMTLn1Oxbv3L9yVfip/vdzl9iJc95kHbBr85cdTAwMDCIT5Ulg/7wIVx1MDAxZTUvYb9JXHUwMDFht9F3wf2uk2Q0iuMsXHUwMDFkXHUwMDBlXHUwMDFhXHUwMDA21VO7auPTXHUwMDE2mGlcYnN0I3xcdTAwMGU24DVjzWMtXHQ+icJXXHUwMDE55VWbZ11VXcl9cSmheCU4QVx1MDAxZT92b0a7XHUwMDE57X+MXHUwMDA2jFGp4Ww0e/thICzlzNj8lnKyXHUwMDFk2lDYPl5ZbOGP03ubusWCa/Zw7Fx1MDAxY39cdTAwMDCLqmbvIn0=<!-- payload-end -->
<defs> <defs>
<style> <style class=\\"style-fonts\\">
@font-face { @font-face {
font-family: \\"Virgil\\"; font-family: \\"Virgil\\";
src: url(\\"https://excalidraw.com/Virgil.woff2\\"); src: url(\\"https://excalidraw.com/Virgil.woff2\\");