通过 Ajax 加载你的 SVG Sprite

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

假设您正在构建一个 SVG 图标系统。您正在手动构建一个包含 符号 的 SVG sprite,或者使用像 IcoMoongrunt-svgstore 这样的构建工具为您创建它。

您如何处理这个 sprite.svg 文件呢?

一种选择是在文档的顶部包含它,然后使用 <use> 标签进行引用。

...

</head>

<body>

  <!-- include it here -->
  <?php include_once("svg/sprite.svg"); ?>

  ...

  <!-- use it here -->
  <a href="/" class="logo">
    <svg class="logo">
      <use xlink:href="#logo" />
    </svg>
  </a>

这种方法有效,但它没有很好地利用缓存。如果网站进行 HTML 缓存,每个页面都将包含这个相同的大块 SVG 内容,这会增加文件大小。更不用说 HTML 解析器需要在每个页面加载时读取文档中的所有这些内容,然后再继续处理其他内容。

可能更好的方法是利用浏览器缓存,就像我们对所有其他资源所做的那样。我们可以通过 使我们的 <use> 标签链接到外部资源 来实现这一点。但是某些浏览器在处理这种情况时存在问题。主要是任何版本的 IE 和一些旧版本的 WebKit。

SVG for Everybody我们在这里推荐过,大部分情况下都能很好地工作。但是,它无法通过其使用的 UserAgent 检测识别到某些浏览器。

另一种方法是始终通过 Ajax 加载 sprite(每次都加载),然后将其注入到页面中。这意味着您可以浏览器缓存该 SVG,并且它可以在任何支持内联 SVG 的地方正常工作。

假设您有一个完整的 SVG 文档,您正在通过 Ajax 加载(sprite.svg),实际上这有点棘手。您必须确保 SVG 具有正确的命名空间,然后再将其附加到页面上(感谢 Amelia)。幸运的是,我们可以利用通常负责此任务的 HTML 解析器。我们通过将 SVG 附加到一个 <div> 中,然后再将该 <div> 附加到页面上来实现这一点。

var ajax = new XMLHttpRequest();
ajax.open("GET", "svg/sprite.svg", true);
ajax.send();
ajax.onload = function(e) {
  var div = document.createElement("div");
  div.innerHTML = ajax.responseText;
  document.body.insertBefore(div, document.body.childNodes[0]);
}

如果您使用 jQuery,它提供的回调数据已经格式化为 SVG 文档,因此您需要将其强制转换为字符串,然后再将其附加到 div,最终附加到页面。

$.get("svg/sprite.svg", function(data) {
  var div = document.createElement("div");
  div.innerHTML = new XMLSerializer().serializeToString(data.documentElement);
  document.body.insertBefore(div, document.body.childNodes[0]);
});

请记住,当您使用这种方式时,只需使用标识符,而不是外部资源。

<svg class="icon" viewBox="0 0 100 100">
  <use xlink:href="#shape-icon-1" />
</svg>

似乎在 IE 和 Android 中 运行良好

还要记住,SVG for Everybody 可以帮助您将标记转换为 <img src="...png">,以便在不支持的浏览器中使用,因此,如果您认为这一点很重要,那么您需要自行处理。