如何在保留图层的同时将 SVG 转换为 PNG?

Posted

技术标签:

【中文标题】如何在保留图层的同时将 SVG 转换为 PNG?【英文标题】:How to convert SVG to PNG while still preserving the layers? 【发布时间】:2021-09-09 17:19:48 【问题描述】:

我的 SVG 图像如下所示:

这是该 SVG 文件的摘录:

<g id="surface1">
    <g clip-path="url(#clip1)" clip-rule="nonzero">
        <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0.140625 0 L 1683.609375 0 L 1683.609375 2390.601562 L 0.140625 2390.601562 Z M 0.140625 0 "/>
        <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0.140625 0 L 1683.609375 0 L 1683.609375 2383.855469 L 0.140625 2383.855469 Z M 0.140625 0 "/>
        <path style=" stroke:none;fill-rule:nonzero;fill:rgb(93.728638%,93.328857%,91.369629%);fill-opacity:1;" d="M 0.140625 0 L 1683.609375 0 L 1683.609375 2383.855469 L 0.140625 2383.855469 Z M 0.140625 0 "/>
    </g>
    <g clip-path="url(#clip2)" clip-rule="nonzero">
        <path style=" stroke:none;fill-rule:nonzero;fill:rgb(85.879517%,85.879517%,85.879517%);fill-opacity:1;" d="M 196.179688 546.039062 C 185.273438 546.039062 176.347656 554.964844 176.347656 565.871094 C 176.347656 565.871094 176.347656 566.121094 176.347656 566.121094 C 177.339844 649.417969 181.304688 977.402344 176.101562 1277.371094 C 169.902344 1624.445312 207.089844 1785.585938 207.089844 1785.585938 L 1341.292969 1785.585938 C 1341.292969 1785.585938 1390.875 1438.511719 1378.476562 1172.011719 C 1366.082031 905.507812 1378.476562 713.378906 1335.09375 632.808594 C 1291.707031 552.238281 764.894531 558.4375 609.949219 552.238281 C 480.042969 547.03125 263.117188 546.289062 196.179688 546.039062 Z M 196.179688 546.039062 "/>
    </g>
    <g clip-path="url(#clip3)" clip-rule="nonzero">
        <g clip-path="url(#clip4)" clip-rule="nonzero">
            <g clip-path="url(#clip5)" clip-rule="nonzero">
                <path style=" stroke:none;fill-rule:nonzero;fill:rgb(73.329163%,42.349243%,17.248535%);fill-opacity:1;" d="M 407.738281 1958.871094 C 400.707031 1854.550781 467.722656 1826.082031 498.4375 1760.117188 C 529.148438 1694.152344 714.296875 1454.164062 1021.128906 1471.179688 C 1327.957031 1488.195312 1477.898438 1544.210938 1492.515625 1710.101562 C 1507.136719 1875.992188 1435.222656 2096.339844 1287.71875 2121.804688 C 1140.21875 2147.269531 707.75 2176.964844 636.011719 2178.085938 C 484.5 2180.882812 412.949219 2036.085938 407.738281 1958.871094 Z M 407.738281 1958.871094 "/>
            </g>
        </g>
    </g>
    ...
</g>

我想知道是否有一个已知的解决方案如何将此 SVG 转换为仅由 PNG Base64 字符串组成的 SVG,其中每个图层中的对象和图层本身都被保留。因此,相对于当前的 SVG 文件只包含 &lt;g&gt;&lt;path&gt; 标签,我想将此 SVG 转换为只包含 &lt;image&gt; 标签的 SVG 文件,其中图像数据包含在 @ 987654327@ 属性,像这样:

&lt;image id="Lager_1" data-name="Lager 1" width="185.9" height="244.95000000000002" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALkAAAD ...

我已经连续 2 周寻找这个问题的解决方案了,所以任何帮助都将不胜感激。对于那些会问“你确定要这样做吗?”的人。答案是是的

我目前最好的猜测是在 javascript 画布上一一加载图层并将它们一一转换为 PNG,然后将标签完全替换为生成的图像字符串。

【问题讨论】:

你的最佳猜测对我来说听起来是个好主意......你有什么问题吗? 我想知道这个用例是什么。请注意,您可以将 CSS 样式应用于 &lt;g&gt; 元素,如 style="display: none;"。可能会让您的想法更容易处理。 目前在做,虽然目前遇到很多问题和bug,但应该是可以的。 感谢Ouroborus,放心,这个问题的解决方案有真实的用例。 究竟是什么用例?作为该领域的“专家”,我没有看到任何一个用例可以有益于这样做。如果您想提高绘制该图像的性能,因为您听说位图渲染比矢量更快,这不会,1. 您的矢量很简单,2. 矢量引擎仍然必须启动,3. 多个光栅将需要解析。总而言之,这里的一切都是值得的,从大小到内存使用,再到解码和光栅化时间。 【参考方案1】:

像 cmets 中的许多人一样,我也对此用例感兴趣,我看不到任何好处。

还有你的:

只是有点难以处理所有特殊情况 关于如何定义 SVG 中的属性, 大量的解析。

让我对为什么如何什么更加好奇strong> 你在做。

只有解析应该由浏览器完成。 程序流程不应超过:

对所有 SVG 重复 克隆原始 SVG https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode 删除您不想要的图层 https://developer.mozilla.org/en-US/docs/Web/API/Element/remove 克隆 SVG 使用 Canvas 转换为二进制图像 循环所有克隆的图像 替换 原始 SVG 中的图层为&lt;image&gt;

您还没有回答所有问题为什么您想要二进制文件

如果你想要一个 SVG &lt;image&gt; 标签(出于某种原因)

您还可以使用以下方式对分层 SVG 进行 dataURI:

function svg2img()
    let svg = document.querySelector('svg');
    let xml = new XMLSerializer().serializeToString(svg);
    let svg64 = btoa(xml); //for utf8: btoa(unescape(encodeURIComponent(xml)))
    return 'data:image/svg+xml;base64,' + svg64;
;

免责声明:我从博客中复制了代码 sn-p;没有测试代码

【讨论】:

与其删除所有不想要的,更安全的解决方案是通过 style 属性隐藏它们,删除可能会改变 CSS 选择器。 但与 html 不同的是,在 SVG 中 &lt;style&gt;&lt;/style&gt; 优先于 style 属性。所以你不能确定style="display:none" 实际上隐藏了元素。移除 &lt;g&gt;&lt;path&gt; 等 SVG 元素不会影响任何“全局”css;除非它们本身包含 &lt;style&gt; 定义。 不,style 的工作方式与 HTML 相同。您可能对 fill 等表示属性的 CSS 等价物感到困惑。是的,删除元素会改变所有规则,如 nth-child()elem ~ elem 等。

以上是关于如何在保留图层的同时将 SVG 转换为 PNG?的主要内容,如果未能解决你的问题,请参考以下文章

将svg转换为png时如何包含CSS样式

如何将 PNG 图像转换为 SVG? [关闭]

如何在ghostscript中将svg、eps和ai转换为png

Ubuntu 下将 svg 图片转换为其他格式 (如 png)

在浏览器中将 SVG 转换为图像(JPEG、PNG 等)

小技巧:如何用 Chrome 将 SVG 转成 PNG