外部文件中的SVG精灵图

25

我在我的应用程序中使用了SVG Sprite创建的图标系统,该系统由IcoMoon App创建。 现在在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" width="752" height="80" 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文件,并将其作为外部资源引用。如何做到这点?

3个回答

27

试试这个:

创建一个名为sprites.svg的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。)

编辑 - 跨浏览器支持:在XML文件中放置SVG精灵元素,并将它们调用到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的示例HTML文件,用于传播defs元素。

<!DOCTYPE HTML>
<html>
<head>
  <title>Sprites</title>
</head>
<body onLoad=loadSprites()>
<svg id=mySVG width="400" height="400">
<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>

谢谢Francis! 解决方案非常好! 幸运的是,我的应用程序不需要IE! - leo
添加 version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 就足以将其加载到 img 标签的 src 中。 - chaggy
@Shyamal -- 不要使用远程文件,而是将“sprite”元素包含在父级svg元素的defs中。 - Francis Hemsher
你能详细说明一下吗?我试过用defs,但还是不能正常工作。顺便说一句,我想把所有的SVG元素都放在一个远程文件中,这样如果以后需要修改就会更容易些。 - Shyamal Parikh
2
@Shyamal - 这只是一个IE应用程序,还是要为所有浏览器安排?通常,我将我的“sprite”元素放在单个XML文件中,并使用XMLHttpRequest将它们调用到应用程序中。我稍后会在上面的原始帖子中编辑并包含一个示例。 - Francis Hemsher
显示剩余3条评论

9

有许多不同的方法可以在文档中嵌入SVG文件,而无需像您在示例标记中所做的那样使用内联SVG代码。将SVG移动到外部文件中确实可以使代码更加清洁、更易编辑。Chris Coyier在CSS-Tricks上有一个关于使用SVG的精彩页面。以下是该文章介绍的技术摘要:

将SVG作为<img>使用

您可以像使用JPG或PNG或任何其他图像文件一样,在<img>标签中嵌入SVG文件:

<img src="kiwi.svg" alt="Kiwi standing on oval">

你可以使用内联width和height属性或在CSS文档中针对SVG图像来调整其宽度和高度。

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

将SVG用作背景图像

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

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

<img> 标签一样,使用这种方法时,高级SVG功能将被禁用。

使用SVG作为<object>

您还可以在<object>中嵌入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?),但我希望您能在这个列表中找到适合您应用程序的方法。请注意,每种方法都有其优点和缺点,因此在选择方法之前要进行更多的研究。还有一些方法可能应该避免使用,比如不要使用<embed>标记,因为它不是任何HTML规范的一部分,而且也许永远都不会成为一部分。

同样,请阅读Chris Coyier的文章,这是我之前提到过的。


1
我已经尝试过这些方法,但都没有成功。谢谢回复! - leo
14
对于SVG精灵,这并没有帮助。 - Mosijava
Leo 询问如何使用外部 SVG 精灵构建 SVG 图标系统,而不是如何嵌入 HTML 页面中的图像。 - Brigo

0

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接