Reputation: 136
How to get an icon from font? Or convert font icon to .svg. I more interest in process (not third-party services)
Upvotes: 6
Views: 9696
Reputation: 17334
If your icon library does not provide a svg icon collection, you can parse and convert any font glyph using opentype.js.
Once you've parsed the font file, you can loop through all available glyphs and create an svg <path>
output via Glyph.getPath(x, y, fontSize)
method.
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/[email protected]/build/decompress_binding.js"></script>
<script src='https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js'></script>
Opentype.js can't parse woff2
files natively.
Fortunately github user yne has found a workaround employing fontello's waWoff2 library.
That's why we need to load the additional waWoff2 script as well.
Upvotes: 5
Reputation: 441
On Windows, what I did was to install the font locally and then go into Character Map and find the symbol I'm looking for. Then I copied and went into Illustrator and created an empty text box, pasted the symbol and then selected the icon font.
Then I just right clicked and converted to outline and exported to SVG.
If you don't have Illustrator, try doing the same thing within Inkscape (it's free).
Upvotes: 4
Reputation: 36
You don't need to convert them into svgs by yourself, they already provide you with the svg code for each and every icon they offer on their official website; You can download the equivalent svg code for an icon of your choice from the following link: https://github.com/FortAwesome/Font-Awesome/tree/master/svgs
There you will find svg code for all the Regular,Solid and Brands icons that you would see on the https://fontawesome.com/icons
Simply goto the https://fontawesome.com/icons choose an icon of your choice that you would like to use in your project and find the corresponding svg file from the list of files that you just downloaded from the above given link; open the svg file in a code editor and copy the shape code from there which you can further consume!!!
HOW TO CONSUME? Well that's another topic....
P.S: Here is the link to the sprite file to download all the svg shapes in one file: https://github.com/FortAwesome/Font-Awesome/tree/master/sprites
Upvotes: 1