Ver Fonte

fix: normalize svg using only absolute sizing (#8854)

Ryan Di há 8 meses atrás
pai
commit
b5652b8e36

+ 12 - 8
packages/excalidraw/components/App.tsx

@@ -3870,14 +3870,18 @@ class App extends React.Component<AppProps, AppState> {
       nextFiles[fileData.id] = fileData;
 
       if (fileData.mimeType === MIME_TYPES.svg) {
-        const restoredDataURL = getDataURL_sync(
-          normalizeSVG(dataURLToString(fileData.dataURL)),
-          MIME_TYPES.svg,
-        );
-        if (fileData.dataURL !== restoredDataURL) {
-          // bump version so persistence layer can update the store
-          fileData.version = (fileData.version ?? 1) + 1;
-          fileData.dataURL = restoredDataURL;
+        try {
+          const restoredDataURL = getDataURL_sync(
+            normalizeSVG(dataURLToString(fileData.dataURL)),
+            MIME_TYPES.svg,
+          );
+          if (fileData.dataURL !== restoredDataURL) {
+            // bump version so persistence layer can update the store
+            fileData.version = (fileData.version ?? 1) + 1;
+            fileData.dataURL = restoredDataURL;
+          }
+        } catch (error) {
+          console.error(error);
         }
       }
     }

+ 24 - 4
packages/excalidraw/element/image.ts

@@ -105,20 +105,40 @@ export const normalizeSVG = (SVGString: string) => {
       svg.setAttribute("xmlns", SVG_NS);
     }
 
-    if (!svg.hasAttribute("width") || !svg.hasAttribute("height")) {
-      const viewBox = svg.getAttribute("viewBox");
-      let width = svg.getAttribute("width") || "50";
-      let height = svg.getAttribute("height") || "50";
+    let width = svg.getAttribute("width");
+    let height = svg.getAttribute("height");
+
+    // Do not use % or auto values for width/height
+    // to avoid scaling issues when rendering at different sizes/zoom levels
+    if (width?.includes("%") || width === "auto") {
+      width = null;
+    }
+    if (height?.includes("%") || height === "auto") {
+      height = null;
+    }
+
+    const viewBox = svg.getAttribute("viewBox");
+
+    if (!width || !height) {
+      width = width || "50";
+      height = height || "50";
+
       if (viewBox) {
         const match = viewBox.match(/\d+ +\d+ +(\d+) +(\d+)/);
         if (match) {
           [, width, height] = match;
         }
       }
+
       svg.setAttribute("width", width);
       svg.setAttribute("height", height);
     }
 
+    // Make sure viewBox is set
+    if (!viewBox) {
+      svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
+    }
+
     return svg.outerHTML;
   }
 };