使用带有外部定义的 SVG

Posted

技术标签:

【中文标题】使用带有外部定义的 SVG【英文标题】:Use an SVG with external definitions 【发布时间】:2022-01-24 00:00:34 【问题描述】:

假设我有一个 SVG 文件。它引用了一个外部 CSS 样式表以及一个外部 SVG 文件。这是一个缩短的版本。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="svg.css"?>
<svg version="1.0" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
   <use xlink:href="defs.svg#myDefs" />
   <g>
      <path class="someClass" d="all the points" />
   </g>
</svg>

外部 CSS 文件提供了一些样式:

.someClass 
   fill: url(#someGradient);

外部引用的 SVG 文件提供了所需的定义。

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">  
   <defs id="myDefs">
      <linearGradient id="someGradient" x1="100%" y1="0%" x2="0%" y2="0%">
         <stop offset="10%" style="stop-color: red;" />
         <stop offset="50%" style="stop-color: white;" />
      </linearGradient>
   </defs>
</svg>

最后,SVG 文件以允许与其他文件交互的方式加载到 DOM 中。

<object data="someFile.svg" type="image/svg+xml"></object>

在 Edge/Chrome 的网络检查器中,我可以看到所有文件都由浏览器加载,包括 SVG、引用的外部 CSS 文件和引用的包含定义的外部 SVG 文件。但我没有让它正常工作。当我使用&lt;defs&gt; 并将它们移动到正在显示的 SVG 文件中时,一切正常。这告诉我 CSS 文件正在正确加载并且正在工作。 &lt;defs&gt; 文件不是。

是否可以不为该 SVG 中的特定图像加载另一个 SVG,而仅为其中包含的定义加载?我已经尝试将渐变名称放在use 链接中,并像我在这里所做的那样为&lt;defs&gt; 提供一个ID。

我为什么要这样做?因为我有几十个交互式 SVG 文件。当用户在屏幕上做某些事情时,他们会得到不同的渐变。目前我必须将这些渐变的定义嵌入到所有 svg 文件中,这使得更改定义变得困难。我想在一个地方做这件事。我想一个可能的选择是将所有 SVG 组合成一个网络重的大文件,然后与对象交互以隐藏和显示它们。如果可能的话,我更喜欢这种方法。

【问题讨论】:

其他人在处理网络服务器上的 html 文件时遇到了同样的问题,并提出了解决方案:动态网页。您能否为您的 SVG 文件做类似的事情,让它们在服务器上动态生成以避免冗余? 【参考方案1】:

你引用渐变的方式,它不起作用。您首先在 &lt;use&gt; 元素中引用 &lt;defs&gt; 元素,然后期望通过其 ID 在其中找到内容。

&lt;use&gt; 元素引用的所有内容都不是父 DOM 的直接部分,而只是封装的影子 DOM 的一部分。在其中定义的 ID 在其外部仍然不可见。

相反,没有什么可以阻止您直接引用外部渐变,如下所示:

.someClass 
   fill: url(defs.svg#someGradient);

【讨论】:

有趣的想法,但是这样做,defs.svg 永远不会被浏览器下载。不显示在网络检查器中。如果使用此 CSS 并将 use 保留在 SVG 中,我可以看到文件已下载,但该样式从不适用。 对我来说,它适用于 Firefox,但不适用于 Chrome。 好的。我也试过fill: url('data:application/xml;utf8;&lt;linearGradient&gt;&lt;/linearGradient&gt;',但没用。我将不得不寻找其他解决方案。

以上是关于使用带有外部定义的 SVG的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有css样式的内联SVG从浏览器保存/导出到图像文件

如何使用带有 material-ui 图标组件的自定义 SVG 文件?

Google Maps API,添加带有标签的自定义 SVG 标记

包含在 HTML 中的带有“img”标签的 SVG 可以链接到带有“image”标签的外部图像吗?

将外部 SVG 图标加载到原生 JavaScript 代码中

对外部 SVG 文件使用 CSS 悬停?