SVG雪碧图:将符号转换为单个SVG图标

6

我有一个如下的SVG精灵:

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;visibility:hidden;">
    <symbol viewBox="0 0 500 500" id="test-icon"><title>test</title><ellipse class="background" id="test-background" fill="#fff" cx="248.8" cy="251.4" rx="246.2" ry="244.8"/>
        <path class="test-frame" d="M249.4 18C121.1 18 16.8 122.3 16.8 250.6S121.3 483 249.4 483 482 378.8 482 250.5 377.7 18 249.4 18m0 480.8c-66 0-128.3-26.4-176.2-73.1C27.6 378.9 1.3 316.5 1.3 249.3s26.3-128.2 73.1-175 109.1-73.1 175-73.1 128.3 26.4 176.2 73.1c46.7 46.8 73.1 109.2 73.1 176.2s-26.4 128.3-73.1 176.2c-46.7 45.6-109 72.1-176.2 72.1"/>
        <path class="test-figure" d="M133.8 103.5v293h232.5V148.9l-22-22-23.4-23.4H133.8zm17.9 22h108.7v12.4H151.7v-12.4zm0 24.8h108.7v12.4H151.7v-12.4zm192.5 211.8H151.7v-24.7h191.2v24.7h1.3zm0-41.2H151.7v-24.7h191.2v24.7h1.3zm0-42.7H151.7v-24.7h191.2v24.7h1.3zm0-44H151.7v-23.4h191.2v23.4h1.3z"/>
    </symbol>
    <symbol viewBox="0 0 500 500" id="test-icon"><title>test</title><ellipse class="background" id="test-background" fill="#fff" cx="248.8" cy="251.4" rx="246.2" ry="244.8"/>
        <path class="test-frame" d="M249.4 18C121.1 18 16.8 122.3 16.8 250.6S121.3 483 249.4 483 482 378.8 482 250.5 377.7 18 249.4 18m0 480.8c-66 0-128.3-26.4-176.2-73.1C27.6 378.9 1.3 316.5 1.3 249.3s26.3-128.2 73.1-175 109.1-73.1 175-73.1 128.3 26.4 176.2 73.1c46.7 46.8 73.1 109.2 73.1 176.2s-26.4 128.3-73.1 176.2c-46.7 45.6-109 72.1-176.2 72.1"/>
        <path class="test-figure" d="M133.8 103.5v293h232.5V148.9l-22-22-23.4-23.4H133.8zm17.9 22h108.7v12.4H151.7v-12.4zm0 24.8h108.7v12.4H151.7v-12.4zm192.5 211.8H151.7v-24.7h191.2v24.7h1.3zm0-41.2H151.7v-24.7h191.2v24.7h1.3zm0-42.7H151.7v-24.7h191.2v24.7h1.3zm0-44H151.7v-23.4h191.2v23.4h1.3z"/>
    </symbol>
    <symbol viewBox="0 0 500 500" id="test-icon"><title>test</title><ellipse class="background" id="test-background" fill="#fff" cx="248.8" cy="251.4" rx="246.2" ry="244.8"/>
        <path class="test-frame" d="M249.4 18C121.1 18 16.8 122.3 16.8 250.6S121.3 483 249.4 483 482 378.8 482 250.5 377.7 18 249.4 18m0 480.8c-66 0-128.3-26.4-176.2-73.1C27.6 378.9 1.3 316.5 1.3 249.3s26.3-128.2 73.1-175 109.1-73.1 175-73.1 128.3 26.4 176.2 73.1c46.7 46.8 73.1 109.2 73.1 176.2s-26.4 128.3-73.1 176.2c-46.7 45.6-109 72.1-176.2 72.1"/>
        <path class="test-figure" d="M133.8 103.5v293h232.5V148.9l-22-22-23.4-23.4H133.8zm17.9 22h108.7v12.4H151.7v-12.4zm0 24.8h108.7v12.4H151.7v-12.4zm192.5 211.8H151.7v-24.7h191.2v24.7h1.3zm0-41.2H151.7v-24.7h191.2v24.7h1.3zm0-42.7H151.7v-24.7h191.2v24.7h1.3zm0-44H151.7v-23.4h191.2v23.4h1.3z"/>
    </symbol>
</svg>

现在我的问题是:我能否只通过提取符号,然后用svg标签替换符号标签来制作svg?或者我如何实现这种转换为单独的svg?
我想到了一个小脚本,可以从上面的svg-sprite中注入多个svg图标,以便更好地/个别地使用css样式。
问题在于,在sprite中有符号,(据我所知)只能使用。但是,由于它是克隆,因此无法像内联svg那样进行个别样式设置。
编辑: 我发现open-iconic svgIncetor使用img-src和单个svg将其注入到html中。 还要提到的是,我已经阅读了Chris Coyier的以下文章:

基本上我想结合那里使用的技术,拥有一个图标系统,可以基于css和图标精灵(通过js注入的内联svg)具有多颜色图标。据我所知,open-iconic注入器只能注入单个svg,而不是从精灵中注入。

4个回答

8

您不需要进行太多的更改(请参见http://jsfiddle.net/yo8bhxfu/):

  • SVG元素中删除视图框(view box)
  • 调整SVG元素的样式,使其可见并指定正确的大小(取自符号的视图框)
  • symbol标签转换为g标签

如果您另外删除class属性、id属性和标题,那么就更加保险了。

<svg xmlns="http://www.w3.org/2000/svg" style="width:500px; height:500px;">
    <g viewBox="0 0 500 500" id="test-icon">
        <title>test</title>
        <ellipse class="background" id="test-background" fill="#fff" cx="248.8" cy="251.4" rx="246.2" ry="244.8"/>
        <path class="test-frame" d="M249.4 18C121.1 18 16.8 122.3 16.8 250.6S121.3 483 249.4 483 482 378.8 482 250.5 377.7 18 249.4 18m0 480.8c-66 0-128.3-26.4-176.2-73.1C27.6 378.9 1.3 316.5 1.3 249.3s26.3-128.2 73.1-175 109.1-73.1 175-73.1 128.3 26.4 176.2 73.1c46.7 46.8 73.1 109.2 73.1 176.2s-26.4 128.3-73.1 176.2c-46.7 45.6-109 72.1-176.2 72.1"/>
        <path class="test-figure" d="M133.8 103.5v293h232.5V148.9l-22-22-23.4-23.4H133.8zm17.9 22h108.7v12.4H151.7v-12.4zm0 24.8h108.7v12.4H151.7v-12.4zm192.5 211.8H151.7v-24.7h191.2v24.7h1.3zm0-41.2H151.7v-24.7h191.2v24.7h1.3zm0-42.7H151.7v-24.7h191.2v24.7h1.3zm0-44H151.7v-23.4h191.2v23.4h1.3z"/>
    </g>
</svg>

SVG只是多个符号的包装器,只是添加了一些内容,使其看起来更像真正的精灵。但是我可以从你的回答中得出的基本上是,用<g>标签替换<symbol>标签没有问题,我可以继续进行。 - Faenor
不过那并不完全相同,符号更像是<svg>而不是<g>。如果您使用嵌套的SVG标签,它应该可以正常工作。请注意,如果您使用<g>元素,则将忽略内部的viewBox属性。 - Erik Dahlström
确实,在 g 元素上不是有效的 viewBox 属性。您可能希望将其设置在 svg 元素上? - geedubb
这对我的简单用例起作用了。我能够实际操作SVG并在Illustrator中看到图层,这就是我所需要的。谢谢! - jClark

2

我改进了Bogdan的代码,创建了一个脚本来解析任何精灵到它的原始SVG。

import {toHtml} from "hast-util-to-html";
import {parse} from "svg-parser";
import * as fs from 'fs';


fs.readFile('input/path/sprite.svg', 'utf8', function (err, contents) {
    const parsed = parse(contents);
    const symbols = parsed.children[0].children;
    symbols.forEach(symbol => {
        const name = symbol.properties.id;
        symbol.tagName = "svg";
        let newIcon = toHtml(symbol);
        fs.writeFile(`output/path/${name}.svg`, newIcon, () => {
            console.log(name);
        });
    });
})

只需添加您的精灵路径和输出路径,它将在输出文件夹中生成带有其ID的内部SVG。

您可以在gist中找到代码


2

我使用Nodejssvg-parser创建了一个小脚本,用于拆分SVG图标精灵文件:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <symbol id="act" viewBox="0 0 48 48">
      <path d="M24 22c0.552 0 1-0.448 1-1v-18c0-0.552-0.448-1-1-1s-1 0.448-1 1v18c0 0.552 0.448 1 1 1z" />
      <path 
        d="M33.027 8.148c0 0-0.010 0.013-0.012 0.015-0.152-0.094-0.322-0.163-0.515-0.163-0.552 0-1 0.448-1 1 0 0.377 0.217 0.693 0.525 0.864 0.004 0.004-0.001 0.015 0.004 0.018 5.503 2.817 9.971 8.868 9.971 16.118 0 9.625-7.866 18-18 18-10.17 0-18-8.375-18-18 0-7.33 4.443-13.31 9.972-16.118 0.005-0.002 0-0.014 0.003-0.018 0.308-0.171 0.525-0.487 0.525-0.864 0-0.552-0.448-1-1-1-0.191 0-0.359 0.068-0.511 0.16-0.002-0.002-0.011-0.015-0.011-0.015-6.513 3.298-10.978 10.055-10.978 17.855 0 11.046 8.954 20 20 20s20-8.954 20-20c0-7.798-4.462-14.553-10.973-17.852z" />
    </symbol>
    ...
  </defs>
</svg>

const fs = require('fs');
const { parse } = require('svg-parser');

// Read from sprite file
fs.readFile('file.svg', 'utf8', function (err, contents) {
  console.log(err);
  const parsed = parse(contents);
  const symbols = parsed.children[0].children[0].children;

  symbols.forEach(symbol => {
    let paths = '';
    const name = symbol.properties.id;
    symbol.children.forEach(path => {
      paths = paths + `<path d="${path.properties.d}" />`
    });

    // Build SVG content
    const newIcon = `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50">
      <g>
        ${paths}
      </g>
    </svg>`

    // White to file
    fs.writeFile(`export/${name}.svg`, newIcon, () => {
      console.log(name);
    });
  });

});

0

我使用了Codo的答案,但在我的情况下它并没有完全起作用。我找到了一个适用于SVG的解决方案:(其中包括<use xlink:href=和优化为<path>

(使用Chrome或类似的开发工具)

  1. 检查SVG,找到<use xlink:href=元素
  2. 展开该元素,并展开#shadow-root(您可能需要在开发工具设置中启用Shadow DOM)
  3. 将SVG元素复制到文本编辑器中
  4. 确保有一个包含路径和形状的结构<g>,如下所示:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 480">
  <g>
    ...
  </g>
</svg>
  1. (可选)使用https://jakearchibald.github.io/svgomg/清理SVG文件
  2. 将文件保存为.svg

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