外部文件中的 SVG 精灵

Posted

技术标签:

【中文标题】外部文件中的 SVG 精灵【英文标题】:SVG sprite in external file 【发布时间】:2014-05-24 11:26:29 【问题描述】:

我正在为我的应用程序使用由 IcoMoon App 创建的带有 SVG Sprite 的图标系统。 在 index.html 我现在有这样的东西:

<html>
<head>...</head>
<body>
<svg display="none" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"   viewBox="0 0 752 80">
    <defs>
    <g id="icon-home">
        <path class="path1" d="M32 18.451l-16-12.42-16 12.42v-5.064l16-12.42 16 12.42zM28 18v12h-8v-8h-8v8h-8v-12l12-9z" />
    </g>
    <g id="icon-camera">
        <path class="path1" d="M9.5 19c0 3.59 2.91 6.5 6.5 6.5s6.5-2.91 6.5-6.5-2.91-6.5-6.5-6.5-6.5 2.91-6.5 6.5zM30 8h-7c-0.5-2-1-4-3-4h-8c-2 0-2.5 2-3 4h-7c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h28c1.1 0 2-0.9 2-2v-18c0-1.1-0.9-2-2-2zM16 27.875c-4.902 0-8.875-3.973-8.875-8.875 0-4.902 3.973-8.875 8.875-8.875 4.902 0 8.875 3.973 8.875 8.875 0 4.902-3.973 8.875-8.875 8.875zM30 14h-4v-2h4v2z" />
    </g>
    </defs>
</svg>   
...some html code...
<!-- an image -->
<svg class="icon" viewBox="0 0 32 32"><use xlink:href="#icon-home"></use></svg>
</body>
<html>

我需要将 svg sprite 移动到文件中,然后将其作为外部资源包含在内。 我该怎么做?

【问题讨论】:

【参考方案1】:

试试这个:

创建一个SVG 文件,sprites.svg

将以下内容放入其中:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
  <path id="icon-home" class="path1" d="M32 18.451l-16-12.42-16 12.42v-5.064l16-12.42 16 12.42zM28 18v12h-8v-8h-8v8h-8v-12l12-9z" />
  <path id="icon-camera" class="path1" d="M9.5 19c0 3.59 2.91 6.5 6.5 6.5s6.5-2.91 6.5-6.5-2.91-6.5-6.5-6.5-6.5 2.91-6.5 6.5zM30 8h-7c-0.5-2-1-4-3-4h-8c-2 0-2.5 2-3 4h-7c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h28c1.1 0 2-0.9 2-2v-18c0-1.1-0.9-2-2-2zM16 27.875c-4.902 0-8.875-3.973-8.875-8.875 0-4.902 3.973-8.875 8.875-8.875 4.902 0 8.875 3.973 8.875 8.875 0 4.902-3.973 8.875-8.875 8.875zM30 14h-4v-2h4v2z" />
</svg>

然后,只要您想包含在 use 元素中。

<svg class="icon" viewBox="0 0 32 32">
  <use xlink:href="sprites.svg#icon-home" />
</svg>

(此时,Internet Explorer 有问题。IE 需要不同的方法。如果你愿意,我也可以展示 IE 的必要条件)

编辑 - 跨浏览器支持:将 SVG sprite 元素放在 XML 文件中并将它们调用到 defs 元素中。

XML 文件,名为 sprites.xml:

<?xml version="1.0" encoding="UTF-8"?>
<SPRITES xmlns="http://www.w3.org/2000/svg">
<path id="iconHome"  d="M32 18.451l-16-12.42-16 12.42v-5.064l16-12.42 16 12.42zM28 18v12h-8v-8h-8v8h-8v-12l12-9z" />
<path id="iconCamera"  d="M9.5 19c0 3.59 2.91 6.5 6.5 6.5s6.5-2.91 6.5-6.5-2.91-6.5-6.5-6.5-6.5 2.91-6.5 6.5zM30 8h-7c-0.5-2-1-4-3-4h-8c-2 0-2.5 2-3 4h-7c-1.1 0-2 0.9-2 2v18c0 1.1 0.9 2 2 2h28c1.1 0 2-0.9 2-2v-18c0-1.1-0.9-2-2-2zM16 27.875c-4.902 0-8.875-3.973-8.875-8.875 0-4.902 3.973-8.875 8.875-8.875 4.902 0 8.875 3.973 8.875 8.875 0 4.902-3.973 8.875-8.875 8.875zM30 14h-4v-2h4v2z" />
</SPRITES>

使用 javascript 传播 defs 元素的示例 HTML 文件。

<!DOCTYPE HTML>
<html>
<head>
  <title>Sprites</title>
</head>
<body onLoad=loadSprites()>
<svg id=mySVG  >
<defs id="spriteDefs" />
    <use xlink:href="#iconHome" transform="translate(100 100)" />
    <use xlink:href="#iconHome" transform="translate(200 100)" />
    <use xlink:href="#iconHome" transform="translate(300 100)" />
    <use xlink:href="#iconCamera" transform="translate(100 200)" />
    <use xlink:href="#iconCamera" transform="translate(200 200)" />
    <use xlink:href="#iconCamera" transform="translate(300 200)" />
    <use xlink:href="#iconHome" transform="translate(200 300)" />
</svg>
<script>
function loadSprites()

    var xmlFile="sprites.xml"
    var loadXML = new XMLHttpRequest;
    loadXML.onload = callback;
    loadXML.open("GET", xmlFile, true);
    loadXML.send();
    function callback()
    
        //---responseText---
        var xmlString=loadXML.responseText
        //---DOMParser---
        var parser = new DOMParser();
        var mySpritesDoc=parser.parseFromString(xmlString,"text/xml").documentElement ;
        var addSprites=mySpritesDoc.childNodes
        for(var k=0;k<addSprites.length;k++)
        
           var sprite=addSprites.item(k).cloneNode(true)
           document.getElementById("spriteDefs").appendChild(sprite)
        
    

</script>
</body>
</html>

【讨论】:

谢谢弗朗西斯!非常好的解决方案!幸运的是,我的应用不需要 IE! ios 7.1 Safari 在动态显示(即通过 JavaScript)显示以这种方式嵌入的 SVG 时也存在问题。 添加version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 足以将其加载到img 标签src @Francis 您能否说明如何使用 IE 进行这项工作? @Shyamal - 这只是一个 IE 应用程序,还是适用于所有浏览器?通常,我将我的“精灵”元素放在单个 XML 文件中,并使用 XMLHttpRequest 将它们调用到应用程序中。我将在今天晚些时候的某个时候在对上述原始帖子的编辑中包含一个示例。【参考方案2】:

有很多不同的方法可以将 SVG 文件嵌入到文档中,而无需像在示例标记中那样使用内联 SVG 代码。将 SVG 移动到外部文件肯定会产生更清晰、更可编辑的代码。 Chris Coyier 在 CSS-Tricks 上的 Using SVG 上有一个很棒的页面。以下是该文章中介绍的技术的摘要:

使用 SVG 作为&lt;img&gt;

您可以将 SVG 文件嵌入到 &lt;img&gt; 标签中,就像在 JPG 或 PNG 或任何其他图像文件中一样:

<img src="kiwi.svg" >

您可以使用内联的宽度和高度属性调整 SVG 图像的宽度和高度,或者通过在 CSS 文档中定位您的 SVG 图像。

请注意,出于安全原因,大多数浏览器会禁用脚本、链接和其他使用&lt;img&gt; 标签添加的 SVG 文件的交互性。

使用 SVG 作为背景图片

在您的示例代码中,您似乎将 SVG 文件用作内容图像,但如果 SVG 仅用于美学目的,您可以将 SVG 文件用作 CSS 中的背景图像:

body 
  background: url(kiwi.svg);
  background-size: 100px 82px;
  /* some other CSS probably */

&lt;img&gt; 标签一样,高级 SVG 功能在使用此方法时会被禁用。

使用 SVG 作为&lt;object&gt;

您还可以在&lt;object&gt; 中嵌入 SVG 文件。使用此技术将允许您使用一些高级 SVG 功能,例如脚本:

<object type="image/svg+xml" data="kiwi.svg" class="logo"></object>

在 PHP 中包含 SVG

如果您使用 php 或其他一些服务器端代码,您可以通过编程方式将 SVG 文件插入到页面中。如果您有一些更复杂的应用程序需要动态加载 SVG 文件或其他东西,这种技术可能会很有用。在 PHP 中,您的 SVG 包含如下所示:

<?php include("kiwi.svg"); ?>

结论

几乎可以肯定,还有其他方法可以将 SVG 文件添加到我在此处未介绍的网页(可能是 iframe?),但我希望您能在此列表中找到适用于您的应用程序的方法。请注意,每种方法都有其优点和缺点,因此在选择一种方法之前要进行更多研究。还有一些方法可能应该避免。例如,不要使用&lt;embed&gt; 标签,因为它不是,也可能永远不会是任何 HTML 规范的一部分。

还请阅读我之前提到的Chris Coyier's article。

【讨论】:

我已经尝试过这些方法,但没有成功。感谢您的回复! 对 svg sprite 没有帮助。 leo 询问的是如何使用外部 svg 精灵构建一个 svg 图标系统,而不是如何在 HTML 页面中嵌入图像。【参考方案3】:

另一种方法是生成包含 sprite 文件的 index.html 文件。这是最好的方法,因为这意味着您的 SVG 图标会立即加载。

您可以使用服务器端包含在网络服务器上执行此操作:

Apache Server Side Include with mod_include 对于 S3 和静态文件托管,您可以use a pre-processor like ssi。

【讨论】:

这样做的问题是你会牺牲浏览器缓存。如果您在多个页面上使用相同的 SVG 精灵,精灵将通过网络一次又一次地加载。 @Waruyama 正确;您正在牺牲浏览器缓存并增加最小页面大小。但是,优点是您至少释放了一个 HTTP 请求(如果您使用多个精灵集或加载单个图标,则释放更多)。您正在加载 page.html,而不是占用 2 个 HTTP 请求来加载 page.htmlsprite-set.svg。如果您有一些精灵或者已经使用了大量的 HTTP 请求,那么这种权衡是值得的。我什至会考虑内联/服务器端,包括 CSS 和 JS!

以上是关于外部文件中的 SVG 精灵的主要内容,如果未能解决你的问题,请参考以下文章

内容安全策略正在阻止 Firefox 中的 svg 图标精灵

SVG 和精灵表

如何在 Angular 组件 HTML DOM 中注入 SVG 图标精灵?

React 和 SVG 精灵

在 IE 和 Edge 上拖动 svg 元素的精灵

如果未找到 ID,如何默认 SVG 精灵