如何将字体图标转换为 .svg 格式?

4
如何从字体中获取图标?或将字体图标转换为 .svg。我更感兴趣的是过程(不是第三方服务)。

欢迎来到StackOverflow!你为什么需要这个?我认为对于图标字体提供商来说,这并不正确。 - xKobalt
不确定如何从前端文件中提取它,但您可以尝试在JS画布上打印字符,这样可以让您将画布(带有字符)导出为PNG文件。您可以将此文件输入到矢量化器中(我确定有一个命令行程序可以执行此操作),以将其转换为SVG。 - Tom Anderson
3个回答

4
在Windows上,我所做的是将字体安装在本地,然后进入字符映射表并找到我要查找的符号。 然后我复制并进入Illustrator并创建一个空的文本框,粘贴符号,然后选择图标字体。
然后我只需右键单击并转换为轮廓,然后导出为SVG。
如果您没有Illustrator,请尝试在Inkscape内执行相同操作(它是免费的)。

我使用CorelDraw。就像CptKicks所说,我在Windows上安装了图标字体的TTF版本,然后打开了CorelDraw并使用了符号选项(Ctrl + F11),该选项允许可视化字体中的所有字符并将其拖放到画布上。从那里,您可以导出为SVG。我想您也可以使用免费的Inkscape完成相同的操作。 - Chris Aelbrecht

3

使用opentype.js解析图标字体

如果你的图标库没有提供svg图标集合,你可以使用opentype.js解析和转换任何字体字形。

一旦解析了字体文件,你可以遍历所有可用的字形,并通过Glyph.getPath(x, y, fontSize)方法创建一个svg <path>输出。

示例:从字体文件生成spritesheet

let fontFile = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/fontawesome-webfont.woff2";

// init
loadFont(fontFile, processFont);

//default
let params = {
  fontSize: 100,
  decimals: 2
};

// process font file after loading and parsing
function processFont(font) {
  showGlyphs(font, params)
}


// create svg sprites from font glyphs
function showGlyphs(font, params) {
  // sanitize font name
  let fontFamily = font.tables.name.fontFamily.en.replaceAll(' ', '_').replaceAll('.', '_');
  let unitsPerEm = font.unitsPerEm;
  let ratio = params.fontSize / unitsPerEm;
  let ascender = font.ascender;
  let descender = Math.abs(font.descender);
  let lineHeight = (ascender + descender) * ratio;
  let baseline = +((100 / (ascender + descender)) * descender).toFixed(3) + 2;

  let decimals = params.decimals;
  let glyphs = font.glyphs.glyphs;
  let keys = Object.keys(glyphs).length;
  let htmlOutput = '';
  let useMarkup = '';

  for (let i = 0; i < keys; i++) {
    let glyph = glyphs[i];
    let lineHeight = (ascender + descender) * ratio;
    let leftSB = glyph.leftSideBearing * ratio;
    let rightSB = (glyph.advanceWidth - glyph.xMax) * ratio;
    let glyphW = (glyph.advanceWidth) * ratio;
    let poxX = 0;

    // adjust negative widths
    if ((glyph.advanceWidth + leftSB) < 0) {
      glyphW = Math.abs(leftSB) + Math.abs(glyph.advanceWidth) + Math.abs(rightSB);
      poxX = Math.abs(leftSB);
    }

    // get svg path data
    let path = glyph.getPath(
      poxX,
      ascender * ratio,
      params.fontSize
    ).toSVG(decimals);


    if (Object.hasOwn(glyph, 'points')) {
      // add symbol definitions
      htmlOutput += `<symbol id="symbol_${glyph.name}" data-id="${glyph.index}" viewBox="0 0 ${+(glyphW).toFixed(2)} ${+(lineHeight).toFixed(2)}"> ${path}</symbol>`;

      // add visible <use> instances
      useMarkup += `<svg id="use_wrap_${glyph.name}"  viewBox="0 0 ${+(glyphW).toFixed(2)} ${+(lineHeight).toFixed(2)}"><use href="#symbol_${glyph.name}" /></svg>`;
    }
  }

  // add hidden svg sprite
  htmlOutput = `<svg xmlns="http://www.w3.org/2000/svg" id="sprite_${fontFamily}" style="width:0; height:0; position:absolute; overflow:hidden;">` + htmlOutput + `</svg>` + useMarkup;

  // render html
  svgcontainer.innerHTML = htmlOutput;

}


/**
 * load font via opentype.js
 * decompress woff2 to truetype using
 * https://github.com/fontello/wawoff2
 * Based on yne's comment:
 * https://github.com/opentypejs/opentype.js/issues/183#issuecomment-1147228025
 */
function loadFont(src, callback) {
  let buffer = {};
  let font = {};
  let ext;

  // is file
  if (src instanceof Object) {
    // get file extension to skip woff2 decompression
    let filename = src[0].name.split(".");
    ext = filename[filename.length - 1];
    buffer = src[0].arrayBuffer();
  }
  // is url
  else {
    let url = src.split(".");
    ext = url[url.length - 1];
    buffer = fetch(src).then((res) => res.arrayBuffer());
  }
  buffer.then((data) => {
    // decompress woff2
    if (ext === "woff2") {
      data = Uint8Array.from(Module.decompress(data)).buffer;
    }
    font = opentype.parse(data);
    callback(font);
  });
}
        svg {
            height: 5em;
            border: 1px solid #ccc;
            display: inline-block;
        }
<h1>Convert fonts to SVG</h1>
<div class="svgcontainer" id="svgcontainer"></div>
<!-- required to parse woff2 fonts -->
<script src="https://unpkg.com/wawoff2@2.0.1/build/decompress_binding.js"></script>
<script src='https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js'></script>

文件格式支持:

  • woff
  • truetype
  • otf
  • woff2

Opentype.js 无法原生解析 woff2 文件。
幸运的是,Github 用户 yne 找到了一种解决方法,使用了 fontello 的 waWoff2 库。 这就是为什么我们需要加载额外的 waWoff2 脚本。

高级 Codepen 示例


1
谢谢您提供的CodePen,这是一个非常好用的资源,可以从WOFF2字体文件中获取SVG,而不像我尝试过的许多其他在线转换器那样存在问题! - TechAurelian
1
@TechAurelian:非常荣幸!实际上,这支笔仍然有一个错误——它并没有真正使用<symbol><use>元素创建精灵表。我修复了它并添加了一些功能(压缩单个图标的SVG)。如果您仍需要以前的版本,可以访问以前的版本 - herrstrietzel

1

你不需要自己将它们转换为svg格式,因为Font Awesome已经为他们在官方网站上提供的每个图标都提供了相应的svg代码;你可以从以下链接下载你选择的图标的等效svg代码: https://github.com/FortAwesome/Font-Awesome/tree/master/svgs

在那里,你会找到所有常规、实心和品牌图标的svg代码,这些图标也可以在https://fontawesome.com/icons上找到。

只需访问https://fontawesome.com/icons,选择你想在项目中使用的图标,然后从你刚才从上述链接下载的文件列表中找到对应的svg文件; 在代码编辑器中打开该svg文件,并从中复制形状代码,你可以进一步使用它!

怎样使用?这又是另一个话题了...

附言:这是一个链接,可以下载所有SVG形状的雪碧图文件: https://github.com/FortAwesome/Font-Awesome/tree/master/sprites


1
你好,感谢您的回答。这是有关font-awesome的有用信息。我还想知道如何从其他字体图标中提取图标,例如由他人构建的字体图标。 - Mykhailo Chernov
1
几乎每个流行的图标提供商都会为其提供的每个图标提供一个SVG形状代码;你只需要进行少量搜索即可。IONICONS提供的图标的SVG可以在以下链接中找到: https://github.com/ionic-team/ionicons/tree/master/src/svg 而LINEA提供的图标的SVG可以在以下链接中找到: https://github.com/linea-io/Linea-Iconset - therealilyaskhan
我建议你使用font-awesome图标的专业版,那里几乎包含了每个人在项目中想要使用的所有可能的图标。专业版附带了SVG文件和SVG精灵,你可以轻松地追踪所选图标的SVG代码!此外,Bootstrap也推荐使用font-awesome。 - therealilyaskhan
1
我创建了 https://iconmeister.github.io/,因为我需要从多个图标集中挑选我真正使用的SVG图标。 - Danny '365CSI' Engelman

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