Mykhailo Chernov
Mykhailo Chernov

Reputation: 136

How to convert font icon to .svg by myself?

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

Answers (3)

herrstrietzel
herrstrietzel

Reputation: 17334

Parse icon fonts with opentype.js

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.

Example: generate spritesheet from font file

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>

File Format support:

  • woff
  • truetype
  • otf
  • woff2

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.

Advanced Codepen example

Upvotes: 5

CptKicks
CptKicks

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

therealilyaskhan
therealilyaskhan

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

Related Questions