やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

IcoMoonでSVGからフォントを作る

 好きなSVG画像をインポートして作れる。

手順

  1. 適当なSVGを入手する
  2. IcoMoonで1のSVGをインポートしフォントとしてDLする
  3. 2のフォントを参照してHTMLで使用する

1. 適当なSVGを入手する

 今回はCryptoIconsという暗号通貨のアイコンを配布するサイトから拝借した。MONAで検索すると出てくるモナコインのうちwhiteタイプのアイコンを使う。

 DLしたら一部を改変する。テキストエディタで開き、<path>fill属性値をwhiteからcurrentColorに書き換える。これで図形の色が文字色になる。ライト/ダークモード変更時などで文字色と同じ色になってくれる。コードは以下。

mona.svg

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path fill="currentColor" d="M16 32C7.163 32 0 24.837 0 16S7.163 0 16 0s16 7.163 16 16-7.163 16-16 16zm7.53-18.586L22.105 7l-2.797 4.414a14.096 14.096 0 00-6.617 0L9.902 7l-1.43 6.414C6.937 14.642 6 16.247 6 18.009c0 3.86 4.476 6.989 9.997 6.989s9.997-3.13 9.997-6.989c-.001-1.762-.93-3.367-2.465-4.595zM10.442 16.35h-.666l1.627-1.876h1.184l-2.145 1.876zm5.504 4.584l-2.766-4.872.683-.39.617 1.085h3.021l.644-1.09.676.402-2.875 4.865zm5.613-4.584l-2.146-1.876h1.192l1.625 1.876h-.671zm-5.6 3.015l1.075-1.82h-2.108l1.033 1.82z"/></svg>

2 IcoMoonでフォント作成する

  1. SVGをアップロードする
  2. SVGの参照名・検索名を設定する
  3. SVGに対応する文字コードを設定・DLする

2-1. SVGをアップロードする

  1. IcoMoonにアクセスする
  2. 画面左上のImportImport Icons)ボタンを押す
  3. 作成したSVGファイルを選ぶ
  4. Untitled SetSVGが追加される

2-2. SVGの参照名・検索名を設定する

  1. 画面上部の✒Editボタンを押す
  2. Untitled Setに追加されたSVGをクリックする
  3. 編集ダイアログが出る
  4. Tagsmona,coinと入力する
  5. Namesmonaと入力する
  6. ×ボタンを押す

2-3. SVGに対応する文字コードを設定・DLする

  1. 画面右下のFontGenerate Font)ボタンを押す
  2. e900の部分を任意の文字コードにする(普通そのままでも問題ない)
  3. 画面右下のDownloadボタンを押す
  4. icomoon-v1.0.zipファイルがDLされる

3 フォントをHTMLで利用する

3-1. DLファイル内容確認

 icomoon-v1.0.zipファイルを展開すると、次のような内容だった。

  • demo.html
  • style.css
  • fonts/
    • icomoon.svg
    • icomoon.ttf
    • icomoon.woff
  • demo-files/
    • demo.css
    • demo.js
  • selection.json
  • ReadMe.txt

3-2. demo.html確認

 demo.htmlをブラウザで閲覧すると、SVGが表示されていることを確認できた。

3-3. 実装方法確認

 最低限、SVG表示に必要なファイルは次の通りである。

  • icomoon.svg
  • style.css
  • demo.html

 このうち、さらに必要最小限に絞って一つのHTMLにすると以下。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>IcoMoon Demo Min</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
@font-face {
  font-family: 'icomoon';
  src:
    url('fonts/icomoon.svg?1sc2gh#icomoon') format('svg'),
    url('fonts/icomoon.woff?1sc2gh') format('woff'),
    url('fonts/icomoon.ttf?1sc2gh') format('truetype');
  font-weight: normal;
  font-style: normal;
  font-display: block;
}
[class^="icon-"], [class*=" icon-"] {
  /* use !important to prevent issues with browser extensions that change fonts */
  font-family: 'icomoon' !important;
  speak: never;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  /* Better Font Rendering =========== */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.icon-mona:before {
  content: "\e900";
}
</style>
</head>

<body>
    <!-- 文字コードやHTML[文字参照][]をそのまま入力しても表示されない -->&#xe900;<br>

    <!-- 所定のclass値を与えると表示される -->
    <i class="icon-mona"></i>
    <span class="icon-mona"></span><br>

    <!-- 所定のfont-familyを与えた上で、文字コードやHTML[文字参照][]を入力すると表示される -->
    <div class="icon-" style="font-family:icomoon;font-size:24px;color:white;background-color:black;">&nbsp;&#xe900;aaaaaaaa
    </div>

    <pre style="font-family:icomoon;">&#xe900;
    </pre>
</body>
</html>

 上記の問題点はCSSurl()参照。これは同一ドメインのみっぽい。CodePenに投稿するとき等に困りそう。もう直接HTMLに埋め込みたい。

 そこでwoffファイルをBase64にして埋め込んでみた。

See the Pen embedded-woff by ytyaru (@ytyaru) on CodePen.

 以下がwoffファイルをBase64に変換したものを参照している部分。

url('data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAU8AAsAAAAABPAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIFKmNtYXAAAAFoAAAAVAAAAFQXVtKHZ2FzcAAAAbwAAAAIAAAACAAAABBnbHlmAAABxAAAATQAAAE0M8wQP2hlYWQAAAL4AAAANgAAADYoScAPaGhlYQAAAzAAAAAkAAAAJAfCA8ZobXR4AAADVAAAABQAAAAUCgAAAGxvY2EAAANoAAAADAAAAAwAKACubWF4cAAAA3QAAAAgAAAAIAAMAFJuYW1lAAADlAAAAYYAAAGGmUoJ+3Bvc3QAAAUcAAAAIAAAACAAAwAAAAMDAAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA6QADwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADgAAAAKAAgAAgACAAEAIOkA//3//wAAAAAAIOkA//3//wAB/+MXBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAA/8AAAAPAAAIAADc5AQAAAAABAAD/wAAAA8AAAgAANzkBAAAAAAEAAP/AAAADwAACAAA3OQEAAAAABgAA/8AEAAPAABsAOwA/AEcASwBPAAAFIicuAScmNTQ3PgE3NjMyFx4BFxYVFAcOAQcGEycHLgEjIgYHNycHDgEVFBceARcWMzI3PgE3NjU0JicFIzczFyc3FzM3Fwc3JzMXBzcjFwIAal1eiygoKCiLXl1qal1eiygoKCiLXl2HLlkYNhwcNxoDWS4lKhkZVzo7QkI6O1cZGSol/l0VNCZrWBYTYRUVXLRFJjTIIkMhQCgoi15dampdXosoKCgoi15dampdXosoKAJTzY0GBgYHAY3NHksqLygpPRESEhE9KSgvKkseXjzPnAwiIw2ckzw8YTs7AAABAAAAAQAA4rKsJ18PPPUACwQAAAAAAOKVPckAAAAA4pU9yQAA/8AEAAPAAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAQAAAEAAAAAAAAAAAAAAAAAAAAFBAAAAAAAAAAAAAAAAgAAAAQAAAAAAAAAAAoAFAAeAJoAAQAAAAUAUAAGAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGljb21vb24AaQBjAG8AbQBvAG8AblZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGljb21vb24AaQBjAG8AbQBvAG8Abmljb21vb24AaQBjAG8AbQBvAG8AblJlZ3VsYXIAUgBlAGcAdQBsAGEAcmljb21vb24AaQBjAG8AbQBvAG8AbkZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=') format('woff');

 残念ながらSVGフォントは埋め込みに対応していないっぽい。以下のようにしても動作しなかった。

SVGをファイルごとBase64化した場合

url('data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiID4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8bWV0YWRhdGE+R2VuZXJhdGVkIGJ5IEljb01vb248L21ldGFkYXRhPgo8ZGVmcz4KPGZvbnQgaWQ9Imljb21vb24iIGhvcml6LWFkdi14PSIxMDI0Ij4KPGZvbnQtZmFjZSB1bml0cy1wZXItZW09IjEwMjQiIGFzY2VudD0iOTYwIiBkZXNjZW50PSItNjQiIC8+CjxtaXNzaW5nLWdseXBoIGhvcml6LWFkdi14PSIxMDI0IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4MjA7IiBob3Jpei1hZHYteD0iNTEyIiBkPSIiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTAwOyIgZ2x5cGgtbmFtZT0ibW9uYSIgZD0iTTUxMi02NGMtMjgyLjc4NCAwLTUxMiAyMjkuMjE2LTUxMiA1MTJzMjI5LjIxNiA1MTIgNTEyIDUxMiA1MTItMjI5LjIxNiA1MTItNTEyLTIyOS4yMTYtNTEyLTUxMi01MTJ6TTc1Mi45NiA1MzAuNzUybC00NS42IDIwNS4yNDgtODkuNTA0LTE0MS4yNDhjLTMxLjc5NiA4LjAwNi02OC4yOTcgMTIuNjAxLTEwNS44NzIgMTIuNjAxcy03NC4wNzctNC41OTQtMTA4Ljk3NC0xMy4yNTJsMy4xMDIgMC42NTEtODkuMjQ4IDE0MS4yNDgtNDUuNzYtMjA1LjI0OGMtNDkuMTItMzkuMjk2LTc5LjEwNC05MC42NTYtNzkuMTA0LTE0Ny4wNDAgMC0xMjMuNTIgMTQzLjIzMi0yMjMuNjQ4IDMxOS45MDQtMjIzLjY0OHMzMTkuOTA0IDEwMC4xNiAzMTkuOTA0IDIyMy42NDhjLTAuMDMyIDU2LjM4NC0yOS43NiAxMDcuNzQ0LTc4Ljg4IDE0Ny4wNDB6TTMzNC4xNDQgNDM2LjhoLTIxLjMxMmw1Mi4wNjQgNjAuMDMyaDM3Ljg4OGwtNjguNjQtNjAuMDMyek01MTAuMjcyIDI5MC4xMTJsLTg4LjUxMiAxNTUuOTA0IDIxLjg1NiAxMi40OCAxOS43NDQtMzQuNzJoOTYuNjcybDIwLjYwOCAzNC44OCAyMS42MzItMTIuODY0LTkyLTE1NS42OHpNNjg5Ljg4OCA0MzYuOGwtNjguNjcyIDYwLjAzMmgzOC4xNDRsNTItNjAuMDMyaC0yMS40NzJ6TTUxMC42ODggMzQwLjMybDM0LjQgNTguMjRoLTY3LjQ1NmwzMy4wNTYtNTguMjR6IiAvPgo8L2ZvbnQ+PC9kZWZzPjwvc3ZnPg==') format('svg');

SVGのテキスト内容をBase64化した場合

url('data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIiA+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQo8bWV0YWRhdGE+R2VuZXJhdGVkIGJ5IEljb01vb248L21ldGFkYXRhPg0KPGRlZnM+DQo8Zm9udCBpZD0iaWNvbW9vbiIgaG9yaXotYWR2LXg9IjEwMjQiPg0KPGZvbnQtZmFjZSB1bml0cy1wZXItZW09IjEwMjQiIGFzY2VudD0iOTYwIiBkZXNjZW50PSItNjQiIC8+DQo8bWlzc2luZy1nbHlwaCBob3Jpei1hZHYteD0iMTAyNCIgLz4NCjxnbHlwaCB1bmljb2RlPSImI3gyMDsiIGhvcml6LWFkdi14PSI1MTIiIGQ9IiIgLz4NCjxnbHlwaCB1bmljb2RlPSImI3hlOTAwOyIgZ2x5cGgtbmFtZT0ibW9uYSIgZD0iTTUxMi02NGMtMjgyLjc4NCAwLTUxMiAyMjkuMjE2LTUxMiA1MTJzMjI5LjIxNiA1MTIgNTEyIDUxMiA1MTItMjI5LjIxNiA1MTItNTEyLTIyOS4yMTYtNTEyLTUxMi01MTJ6TTc1Mi45NiA1MzAuNzUybC00NS42IDIwNS4yNDgtODkuNTA0LTE0MS4yNDhjLTMxLjc5NiA4LjAwNi02OC4yOTcgMTIuNjAxLTEwNS44NzIgMTIuNjAxcy03NC4wNzctNC41OTQtMTA4Ljk3NC0xMy4yNTJsMy4xMDIgMC42NTEtODkuMjQ4IDE0MS4yNDgtNDUuNzYtMjA1LjI0OGMtNDkuMTItMzkuMjk2LTc5LjEwNC05MC42NTYtNzkuMTA0LTE0Ny4wNDAgMC0xMjMuNTIgMTQzLjIzMi0yMjMuNjQ4IDMxOS45MDQtMjIzLjY0OHMzMTkuOTA0IDEwMC4xNiAzMTkuOTA0IDIyMy42NDhjLTAuMDMyIDU2LjM4NC0yOS43NiAxMDcuNzQ0LTc4Ljg4IDE0Ny4wNDB6TTMzNC4xNDQgNDM2LjhoLTIxLjMxMmw1Mi4wNjQgNjAuMDMyaDM3Ljg4OGwtNjguNjQtNjAuMDMyek01MTAuMjcyIDI5MC4xMTJsLTg4LjUxMiAxNTUuOTA0IDIxLjg1NiAxMi40OCAxOS43NDQtMzQuNzJoOTYuNjcybDIwLjYwOCAzNC44OCAyMS42MzItMTIuODY0LTkyLTE1NS42OHpNNjg5Ljg4OCA0MzYuOGwtNjguNjcyIDYwLjAzMmgzOC4xNDRsNTItNjAuMDMyaC0yMS40NzJ6TTUxMC42ODggMzQwLjMybDM0LjQgNTguMjRoLTY3LjQ1NmwzMy4wNTYtNTguMjR6IiAvPg0KPC9mb250PjwvZGVmcz48L3N2Zz4=
') format('svg');

 SVGテキストエディタで編集できそうなので、是非ともこちらを使いたかったのだが。残念。

3-4. 入力方法確認

 今回、対象SVG文字コードポイントe900を割り当てた。これを各方法で入力すると以下の通り。

設定
Name mona
文字コードポイント e900
種別
文字コード
HTML文字参照 &#xe900;
HTML <i class="icon-mona"></i>

 文字コードは豆腐(□)みたいに表示されていると思う。これはコードポイントe900に該当するフォント・グリフが存在しないから。グリフがないものはすべて豆腐で表示されてしまう。それだと視認性がなくて困るのでHTML文字参照や、CSSを使った実装方法がある。

 HTML内では次のように使う。キモはclass属性値にicon-monaを与えている所。<i>以外の要素でもOK。

<i class="icon-mona"></i>

 文字コードで指定する方法もある。このとき、要素のstyle属性値にfont-family:icomoonを指定する必要がある。

<div style="font-family:icomoon;"></div>

 HTML文字参照文字コードを直接指定する方法は以下。

<div style="font-family:icomoon;">&#xe900;</div>

 &#xe900;文字参照の部分。このうちe900の部分が今回設定した文字コードである。それ以外の&#x;はHTML文字参照用メタ文字。そのうちxは16進数を意味する。つまりe900はコードポイントを16進数値である。他にも10進数値で表現できるが、16進数値のほうが桁数が少なくなり容量を削減できる。

 文字コード確認ツールを入力し確認ボタンを押すと、数値文字参照(16進数)の欄に&#xE900;と出る。大文字と小文字の違いはあるが&#xe900;と同じである。

 文字参照のほうがテキストエディタにおける可読性が高い。

おまけ

SVGフォント

 IcoMoonで出力されたフォントのうちSVGフォントの内容は以下。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="mona" d="M512-64c-282.784 0-512 229.216-512 512s229.216 512 512 512 512-229.216 512-512-229.216-512-512-512zM752.96 530.752l-45.6 205.248-89.504-141.248c-31.796 8.006-68.297 12.601-105.872 12.601s-74.077-4.594-108.974-13.252l3.102 0.651-89.248 141.248-45.76-205.248c-49.12-39.296-79.104-90.656-79.104-147.040 0-123.52 143.232-223.648 319.904-223.648s319.904 100.16 319.904 223.648c-0.032 56.384-29.76 107.744-78.88 147.040zM334.144 436.8h-21.312l52.064 60.032h37.888l-68.64-60.032zM510.272 290.112l-88.512 155.904 21.856 12.48 19.744-34.72h96.672l20.608 34.88 21.632-12.864-92-155.68zM689.888 436.8l-68.672 60.032h38.144l52-60.032h-21.472zM510.688 340.32l34.4 58.24h-67.456l33.056-58.24z" />
</font></defs></svg>

 いわゆるSVGフォントという奴。唯一テキストで記述できるため個人的には使いたいのだが、サポート状況が悪い。

selection.json

 IcoMoonでフォントをDLし展開したらselection.jsonファイルがある。ここには主要なデータがJSON形式で入っている。グリフを示すpathname, tagsの他、各種設定値がある。

{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M512 1024c-282.784 0-512-229.216-512-512s229.216-512 512-512 512 229.216 512 512-229.216 512-512 512zM752.96 429.248l-45.6-205.248-89.504 141.248c-31.796-8.006-68.297-12.601-105.872-12.601s-74.077 4.594-108.974 13.252l3.102-0.651-89.248-141.248-45.76 205.248c-49.12 39.296-79.104 90.656-79.104 147.040 0 123.52 143.232 223.648 319.904 223.648s319.904-100.16 319.904-223.648c-0.032-56.384-29.76-107.744-78.88-147.040zM334.144 523.2h-21.312l52.064-60.032h37.888l-68.64 60.032zM510.272 669.888l-88.512-155.904 21.856-12.48 19.744 34.72h96.672l20.608-34.88 21.632 12.864-92 155.68zM689.888 523.2l-68.672-60.032h38.144l52 60.032h-21.472zM510.688 619.68l34.4-58.24h-67.456l33.056 58.24z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["mona","coin"]},"attrs":[{}],"properties":{"order":2,"id":0,"name":"mona","prevSize":32,"code":59648},"setIdx":0,"setId":2,"iconIdx":0}],"height":1024,"metadata":{"name":"icomoon"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icomoon","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false,"showSelector":false,"showMetrics":false,"showMetadata":false,"showVersion":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":50,"showCodes":true,"gridSize":16}}

 これを使えばSVGデータ等を動的生成できそう。

まとめ

 IcoMoonSVG画像に対応する文字コードポイントを割り当てて外字として使用できるようにする。そのためのファイルとしてSVG, TTF, WOFFという三つの形式のファイルが出力された。これをHTML上で参照する方法は三つある。文字コード、HTML文字参照CSSクラス属性値参照である。