如何从字体中获取图标?或将字体图标转换为 .svg。我更感兴趣的是过程(不是第三方服务)。
如果你的图标库没有提供svg图标集合,你可以使用opentype.js解析和转换任何字体字形。
一旦解析了字体文件,你可以遍历所有可用的字形,并通过Glyph.getPath(x, y, fontSize)
方法创建一个svg <path>
输出。
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>
Opentype.js 无法原生解析 woff2
文件。
幸运的是,Github 用户 yne 找到了一种解决方法,使用了 fontello 的 waWoff2 库。
这就是为什么我们需要加载额外的 waWoff2 脚本。
<symbol>
和<use>
元素创建精灵表。我修复了它并添加了一些功能(压缩单个图标的SVG)。如果您仍需要以前的版本,可以访问以前的版本。 - herrstrietzel你不需要自己将它们转换为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