【问题标题】:svg-sprite: symbol conversion to single svg iconsvg-sprite:符号转换为单个 svg 图标
【发布时间】:2015-03-06 13:51:57
【问题描述】:

我有一个像下面这样的 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-tag 替换 symbol-tag 来从符号中制作一个 svg 吗?或者我怎样才能实现这种转换为单独的 svg?

我想到了一个小脚本,它可以像上面一样从 svg-sprite 中注入几个 svg 图标,因此这些图标可以更好地/单独地通过 css 设置样式。

这里的问题是,在精灵中有符号,(据我所知)只能与&lt;use xlink:href&gt; 一起使用。但是图标不能像 inline svg 那样单独设置样式(因为它是一个克隆)。

编辑: 我发现了使用 img-src 和单个 svgs 注入 html 的开放标志性 svgIncetor。 另外值得一提的是,我已经阅读了 Chris Coyier 的以下文章:

基本上,我想将那里使用的技术组合成一个图标系统,该系统可以具有基于 css 和 icon-sprite 的多色图标(通过 js-inject 使用内联 svg)。 开放式图标注入器只能注入单个 svgs 而不能从 sprites afaik 注入。

【问题讨论】:

    标签: javascript svg


    【解决方案1】:

    您无需进行太多更改(请参阅http://jsfiddle.net/yo8bhxfu/):

    • SVG 元素中移除视图框
    • 调整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 标签就可以了,我很高兴。
    • 虽然不太一样,符号更像是 而不是 。它应该适用于嵌套的 svg 标签。请注意,如果您使用 元素,内部的 viewBox 属性将被忽略。
    • 确实viewBoxg 元素上无效。您可能希望在 svg 元素上使用它?
    • 这适用于我的简单用例。能够实际操作 SVG 并在 Illustrator 中查看图层,这正是我所需要的。谢谢!
    【解决方案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);
        });
      });
    
    });
    

    【讨论】:

      【解决方案3】:

      我使用了 Codo 的答案,但在我的情况下它并没有完全起作用。我遇到了一个适用于 SVG 的解决方案:(它是 &lt;use xlink:href=,而 svg 优化为 &lt;path&gt;s)

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

      1. 检查 svg,找到 &lt;use xlink:href= 元素
      2. 展开元素,展开#shadow-root(您可能需要在开发工具设置中启用Shadow DOM)
      3. 将里面的 svg 元素复制到文本编辑器中
      4. 确保有一个包含路径和形状的结构&lt;g&gt;,如下所示:
      <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

      【讨论】:

        【解决方案4】:

        我改进了 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);
                });
            });
        })
        

        只需添加您的精灵路径和输出路径,它就会在输出文件夹中生成带有 ids 的内部 svgs。

        你可以在gist找到代码

        【讨论】:

          猜你喜欢
          • 2020-03-03
          • 2016-05-26
          • 1970-01-01
          • 2020-04-20
          • 2015-08-03
          • 2017-06-18
          • 2020-01-24
          • 2016-02-28
          • 1970-01-01
          相关资源
          最近更新 更多