【问题标题】:How can I refer to an internal gradient definition inside an SVG sprite symbol?如何引用 SVG 精灵符号内的内部渐变定义?
【发布时间】:2014-07-17 14:54:23
【问题描述】:

总结: 一个 SVG 精灵包含五个图标 <symbol> 块,其中一个通过 ID 引用其自己的渐变定义。它不再能够找到这个渐变并正确渲染。

JSFIDDLE: http://jsfiddle.net/Qtq24/1/


我正在将一些图形转换为 SVG,并且由于它们是图标(在这种情况下用于社交网络配置文件),因此我想将它们保存在精灵中(就像我之前使用 PNG 一样)。

我关注了this guide to SVG sprites on CSS-tricks.com(以及this follow-up which advises using <symbol> instead of <g>)。

我现在有一个 SVG sprite 文件,social-sprite.svg,您可以在here查看完整文件。

这是一个完整的<svg> 块,包含五个不同的<symbol> 块,每个块都有一个id 和一个viewBox 属性。在每种情况下,我通过在 Adob​​e Illustrator 中准备官方图标并保留已处理代码的相关部分来获得每个符号的 SVG 代码。

.svg 文件在<body> 标签打开后立即通过 PHP 包含(这就是为什么其中的主要<svg> 容器标有style="display: none;"),因此对每个符号的引用从HTML。

四个图标完美运行,我唯一遇到的问题是 YouTube 图标,因为它使用内部定义的渐变。这是 SVG 代码的 YouTube 部分:

<symbol id="youtube" viewBox="0 0 400 281.641">
    <path id="Triangle" fill="#FFFFFF" d="M159.845,191.73l106.152-54.999L159.845,81.348V191.73z"/>
    <path id="The_Sharpness" opacity="0.12" fill-rule="evenodd" clip-rule="evenodd" fill="#420000" d="M159.845,81.348l93.091,62.162
    l13.061-6.778L159.845,81.348z"/>
    <g id="Lozenge">
        <g>
            <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="200.4204" y1="2.6162" x2="200.4204" y2="278.9292">
                <stop  offset="0" style="stop-color:#E52D27"/>
                <stop  offset="1" style="stop-color:#BF171D"/>
            </linearGradient>
            <path fill="url(#SVGID_1_)" d="M392.928,62.226c0,0-3.839-27.073-15.617-38.995C362.371,7.583,345.626,7.506,337.947,6.59
            c-54.975-3.974-137.441-3.974-137.441-3.974h-0.171c0,0-82.464,0-137.44,3.974c-7.68,0.916-24.419,0.993-39.364,16.641
            C11.753,35.153,7.92,62.226,7.92,62.226s-3.929,31.792-3.929,63.583v29.805c0,31.791,3.929,63.582,3.929,63.582
            s3.833,27.073,15.611,38.995c14.945,15.646,34.575,15.152,43.318,16.792c31.43,3.015,133.571,3.946,133.571,3.946
            s82.552-0.124,137.526-4.099c7.679-0.915,24.424-0.993,39.363-16.64c11.778-11.922,15.617-38.995,15.617-38.995
            s3.923-31.791,3.923-63.582v-29.805C396.851,94.017,392.928,62.226,392.928,62.226z M159.863,191.73l-0.018-110.383
            l106.152,55.384L159.863,191.73z"/>
        </g>
    </g>
</symbol>

这在 HTML 中被调用:

<svg width="30" height="21">
    <use xlink:href="#youtube" src="fallback.png" width="30" height="21" />
</svg>

打开的两条路径工作正常,问题是在这个新的组合精灵 SVG 文件中,每个图标分隔为 &lt;symbol&gt;“菱形” &lt;path&gt; 无法找到#SVGID_1_&lt;linearGradient&gt; 的引用。

在 Firefox 中,这会导致菱形显示为白色(我认为,也许它根本没有显示 - 并没有真正研究它):

虽然 Chrome 将其呈现为黑色:

显然两者都不可接受。目前我唯一能做的就是删除路径上的fill="url(#SVGID_1_)",然后用适合 YouTube 徽标的纯红色填充。不过,这不是一个合适的解决方案,即使不考虑以这种方式对 YouTube 徽标进行粗制滥造的事实,他们的品牌准则也不接受这一事实。

我尝试过的事情(但没有成功):

  • 移除包围渐变和路径的两个&lt;g&gt; 包装器,所以整个符号只是&lt;path&gt;-&lt;path&gt;-&lt;linearGradient&gt;-&lt;path&gt;
  • 将渐变定义包装在 &lt;defs&gt; 容器中
  • 将其包装在 &lt;defs&gt; 中,并将其移动到 SVG 文件的顶部,即 YouTube 特定 &lt;symbol&gt; 的范围之外
  • 更改 ID 名称(你永远不知道!)
  • 用百分比而不是像素值重新定义渐变

那么我如何让一个已经在内部的&lt;symbol&gt; 引用一个也在内部的&lt;linearGradient&gt; 定义?


编辑:当整个&lt;svg&gt; 块被标记为style="display: none;" 时,渐变会失败。如果删除此样式,渐变将正确呈现。但提醒一下,添加了这种样式,这样当您导入 SVG 精灵时,它不会立即呈现在页面上,而只是允许您根据需要引用 id 定义的符号。

visibility: hiddenopacity: 0 都允许正确渲染渐变,但显然它们没有提供适当的解决方案,因为它们仍然划定了 SVG 可见时会占用的空间。

在发现这一切之后,我很确定将完全可见的 &lt;svg&gt; 添加到 INSIDE 一个隐藏的容器 &lt;div&gt; 是没有问题的。但是,即使这样也会导致渐变不渲染。我离解决问题还差得远。

【问题讨论】:

  • 您可以尝试将其包装在 标记中吗?
  • @MichaelMullany 那行不通。

标签: css svg gradient


【解决方案1】:

首先请注意对我的问题的修改 - 于是我发现使用 display: none 隐藏 SVG 符号直到我们需要它们是问题所在。

我一直在摆弄并确定了这个“答案”,它远非完美,但在任何此类情况下仍然应该是可靠的。

您需要做的就是将整个&lt;svg&gt; 代码包装在一个&lt;div&gt; 容器中,该容器必须显示但绝不会影响布局,所以我刚刚通过超大杀伤力CSS 完成了这项工作如:

height: 0; width: 0; position: absolute; visibility: hidden;

这很好用。看最后的小提琴:http://jsfiddle.net/Qtq24/5/

如果有人有更好的解决方案,我很想听听,因为这感觉有点老套,但我想没有比必须使用display: none; 更老套的方法了。

【讨论】:

  • 感谢您花时间回答您的问题,我真的很挣扎!
  • SVG 有一些奇怪的地方,如果包含渐变元素的 SVG 是 display:none(或者它的父元素之一),那么无论在哪里引用渐变都不会显示。我不确定这是浏览器的错误还是故意的。
  • 这实际上是解决问题的正确方法,因为浏览器被告知不要渲染display:none; 元素。谢谢
  • 先生,您是救世主
  • 你不能给 SVG 本身提供这些样式吗?
【解决方案2】:

不要使用 style="display: none;"在 SVG 中。你在根 &lt;svg&gt; 元素上有它。 visibility:hidden、height/width="0" 或 &lt;defs&gt; 都是更好的选择。

以前在 Firefox 中存在符号中带有渐变元素的错误。该错误已在许多版本之前修复。原始代码按预期工作。

<svg width="30" height="21">
<symbol id="youtube" viewBox="0 0 400 281.641">
  <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="200.4204" y1="2.6162" x2="200.4204" y2="278.9292">
    <stop  offset="0" style="stop-color:#E52D27"/>
    <stop  offset="1" style="stop-color:#BF171D"/>
  </linearGradient>
    <path id="Triangle" fill="#FFFFFF" d="M159.845,191.73l106.152-54.999L159.845,81.348V191.73z"/>
    <path id="The_Sharpness" opacity="0.12" fill-rule="evenodd" clip-rule="evenodd" fill="#420000" d="M159.845,81.348l93.091,62.162
    l13.061-6.778L159.845,81.348z"/>
    <g id="Lozenge">
        <g>
            <path fill="url(#SVGID_1_)" d="M392.928,62.226c0,0-3.839-27.073-15.617-38.995C362.371,7.583,345.626,7.506,337.947,6.59
            c-54.975-3.974-137.441-3.974-137.441-3.974h-0.171c0,0-82.464,0-137.44,3.974c-7.68,0.916-24.419,0.993-39.364,16.641
            C11.753,35.153,7.92,62.226,7.92,62.226s-3.929,31.792-3.929,63.583v29.805c0,31.791,3.929,63.582,3.929,63.582
            s3.833,27.073,15.611,38.995c14.945,15.646,34.575,15.152,43.318,16.792c31.43,3.015,133.571,3.946,133.571,3.946
            s82.552-0.124,137.526-4.099c7.679-0.915,24.424-0.993,39.363-16.64c11.778-11.922,15.617-38.995,15.617-38.995
            s3.923-31.791,3.923-63.582v-29.805C396.851,94.017,392.928,62.226,392.928,62.226z M159.863,191.73l-0.018-110.383
            l106.152,55.384L159.863,191.73z"/>
        </g>
    </g>
</symbol>

<use xlink:href="#youtube" width="30" height="21" />
</svg>

【讨论】:

  • 我运气不好,罗伯特 - 请参阅 jsfiddle.net/Qtq24/3 - 在 Firefox(白色)和 Chrome(黑色)中的结果与以前一样,尽管已将渐变移出 @,但两者都无法找到渐变987654325@。这实际上是我之前尝试过的事情之一,我敢肯定 - 无论有没有 &lt;defs&gt; 容器......搜索仍在继续。
  • 也很抱歉以某种方式掩盖了您不使用 display: none 的建议 - 如果我早点发现这一点,我会早点得到答案!但如上所述,这是 SVG sprite 所必需的,以防止在加载代码后立即渲染符号。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-20
  • 2017-03-26
  • 2019-05-07
  • 1970-01-01
  • 2019-12-13
相关资源
最近更新 更多