svg要素の基本的な使い方まとめ

Written by defghi1977@xboxLIVE.この文書は全てテキストエディタで作成しています.えーと,そりゃもうゴリゴリと.

16.フォント定義

いかなる環境においても同じ文字の見た目を提供するため,SVGにはフォントを定義し,自分自身に埋め込む仕様が定義されている.本項ではこのフォント機能についてその概略について述べる.非常に広範な知識が要求される割にSVGフォントを直接サポートする環境が少ないので利用する機会がそれほどないものの,簡単にフォントを作れるのは非常に魅力的であり,場合によっては非常に役に立つこともある.なお,本ページの記述は参考となる資料や動作環境の貧弱さから曖昧な点や不足が多々ある事を予めお詫びする.また実際の動作を確認する場合はchrome等のwebkit系のブラウザを利用してほしい.operaでは一部動作が不安定な箇所があるprestoエンジンをサポートするOperaで行って欲しい.

SVGフォント

重要)2014/10以降Windows環境の一部を除きChrome/Opera等のブラウザにおいてもSVGフォントのサポートが為されなくなりました. 従って, 今後はSVGフォントは他の形式のフォントを生成するためのソースコードとしての利用のみ有効です. 従って下記サンプルコードを実際に動作させたい場合は旧Opera(Prestoエンジン/ver12以前)で確認してください.

一般に,出力機器にテキストを表示する際の書体に対する電子データをフォントファイルと呼び,その際の電子化の仕方がフォント形式である.SVGではフォント機能によってフォント(SVGフォント)を自作することが出来る.フォント形式にはこの他にTTF(TrueType Font)やOTF(OpenType Font),Woff(Web Open Font Format),EOT(Embedded OpenType)形式等があるが,SVGフォントはXMLベースのテキストファイルであるため扱いやすい.しかしSVGフォントをサポートする環境は限られており,特にWEBブラウザにおいてはほぼ利用できない.

WEBフォントのソースコードとしてのSVGフォント

SVGフォントはツールを用いて別のフォント形式に変換することが可能である.従ってフォントを自作する場合に,まずSVGフォントを作成しそれをWOFF形式などに変換してWEBブラウザに表示することができる.つまりSVGフォントをフォントを生成するためのソースコードとして活用するのだ.本格的なフォント編集作業でない限り,常用しているSVG編集環境をそのままフォント作成に活かせる点でメリットがある.

以下に代表的なフォント形式の変換を行うツールを示す.

IcoMoonではSVGフォント以外の任意のSVGファイルを直接フォント化することが出来る.

ラスタ画像からSVGフォントを生成する

拙作スクリプトを用いると,PNG形式等のラスタ画像からSVGフォントを生成することが可能だ.同様のことはIncscape等を使っても可能である.

SVGフォントの構造

SVGフォントを含む概念としてのフォントファイルがもつべき情報には次のようなものがある.

従ってSVGフォントについてもこれらの情報が定義出来, 次のような階層構造をとる.

text要素はフォントを使う側であり,font要素はフォントを定義する側である.従ってこの2つの要素はさながら裏と表の関係にあり,text要素での文字列装飾の属性に対応するものがfont-face要素に定められている点に注意すると判りやすい.

具体的な利用法

重要)本項は内容が古くなっています.現状下記のコードが動作する環境はほとんどありません.

svgフォントの機能は大体埋め込みフォントとして利用する外部フォントを参照するの2つの使い途が存在する.

文書に埋め込まれたフォントを利用する

svg要素から埋め込みのsvgフォントを利用するには次のようにする.まず,font要素でsvgフォントの宣言をし,font-face要素でフォント名称を設定する.こうすることで文書内からこのフォントをfont-family属性から参照することが可能となる.

1234567890
<svg viewBox="0 0 200 200">
    <defs>
        <font horiz-adv-x="1024">
            <font-face units-per-em="1024" font-family="svg-font"/>
            <glyph unicode="1" d="M 0,0 h 1024 v 1024 z" />
            <glyph unicode="2" d="M 0,0 v 1024 h 1024 z" />
            <glyph unicode="3" d="M 0,0 l 1024,1024 v -1024 l -1024,1024 z" />
            <glyph unicode="4" d="M 0,0 l 1024,1024 h -1024 l 1024,-1024 z" />
        </font>
    </defs>
    <text font-size="20" font-family="svg-font" y="20">1234567890</text>
</svg>

このフォントをtext要素から参照することで,文字の描画時にグリフ要素の内容が用いられる.つまり,文字「1」「2」「3」「4」の見た目がsvgフォントの内容に従って書き換わるのだ.

このフォントはsvgのtext要素に適用することの他にも,htmlに埋め込まれたsvg要素であれば,一般的なdiv要素などにも適用することが可能である.つまりcssスタイル「font-family:svg-font」を指定することで「1234567890」と言った結果が得られる.

外部フォントを参照する

font-face要素の機能を用いると,外部svgファイルで定義されているsvgフォントを参照することが出来る.つまり,次のようなsvgファイルをsvgフォントとして利用する場合,font-family要素を用意し,その中で外部のsvgフォントを呼び出すようにする.すると先ほどと同様にsvgフォントを文字の描画に利用することが可能となる.

※svgfont.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<font id="MyFont" horiz-adv-x="1024" horiz-origin-x="0" horiz-origin-y="0" vert-origin-x="45" vert-origin-y="90" vert-adv-y="90">
<font-face units-per-em="1024" font-family="MyFont" />
        <glyph unicode="明治" d="M 0,0 h 1024 v 1024 z" />
        <glyph unicode="大正" d="M 0,0 v 1024 h 1024 z" />
        <glyph unicode="昭和" d="M 0,0 l 1024,1024 v -1024 l -1024,1024 z" />
        <glyph unicode="平成" d="M 0,0 l 1024,1024 h -1024 l 1024,-1024 z" />
<glyph glyph-name="1" unicode="1" d="M 197.04,682.98 370.72,912.63 690,912.63 708.8,21 328.49,21 408.3,714.49 187.64,633.45" />
<glyph glyph-name="2" unicode="2" d="M 207.23,911.67 797.33,862.5 840.1,538.74 382.53,210.85 822.98,161.67 882.87,18.2 l -718.41,0 64.15,413.97 423.34,168.02 8.54,188.54 -504.57,-102.47" />
</font>
</defs>
</svg>
1234567890
<svg viewBox="0 0 200 200">
    <defs>
        <font-face font-family="svgfont1">
            <font-face-src>
                <font-face-uri xlink:href="svgfont.svg#myFont" />
            </font-face-src>
        </font-face>
    </defs>
    <text font-size="20" font-family="svgfont1" y="20">1234567890</text>
</svg>

こちらでも文書全体で利用可能だ.例)「1234567890」

@font-face規則を利用する

svgフォントはcssの持つ@font-face規則を使って呼び出すことも出来る.従ってインラインsvgを介さずともhtmlから直接svgフォントを呼び出すことが可能となっている.

1234567890
<svg viewBox="0 0 200 200">
    <style>
        @font-face {
            font-family:'svgfont2';
            src: url(svgfont.svg#MyFont) format("svg");
        }
    </style>
    <text font-size="20" font-family="svgfont2" y="20">1234567890</text>
</svg>

こちらでも文書全体で利用可能だ.例)「1234567890」

補足)フォント設定を含んだインラインsvg要素の取扱い

font要素やfont-face要素等のフォント定義を含んだsvg要素はその文書の中で特別なものとして扱うべきである.javascript等でその内容を変更するといった使い方はスクリプト処理上は正しく動作するだろうが,フォントとしての動作は諦めたほうが良い.※これはsvgフォントの実装がまだまだ発展途上であることを示している.

補足)この他のsvgフォントの呼び出し

上記で示した方法は数あるsvgフォントの呼び出し方法の中でも,比較的安定的な動作が見込めるものである.実はこの他にもsvgフォントを呼び出せる可能性のある記述の仕方が存在しているのだが,必ずしもクロスブラウザで動作するわけではない.言い換えると,svgフォントが動作したと言っても,他の環境で動作しないケースもあるという事なので,動作の確認を行う際は慎重に行いたい.

font:フォントの宣言

font要素はフォントの宣言を行うもので,フォントの特性はfont-face要素に,文字の形はglyph要素にて定義する.外部からフォントの外形を参照する場合は,このfont要素に定義されたidを元にフォントを検索する.(text要素が参照するのはfont-face要素である.)

horiz-origin-x
グリフを書きだす原点位置.
horiz-origin-y
グリフを書きだす原点位置.
horiz-adv-x
横書きにおける次の文字の基準位置.
vert-origin-x
縦書きにおける原点位置.
vert-origin-y
縦書きにおける原点位置.
vert-adv-x
縦書きにおける次の文字の基準位置.

glyph:文字の形

glyph要素はある文字に対する「見た目」=グリフを定義する.この要素は文字毎に定義する必要があるため,ascii文字だけならそれほどでもないが,日本語フォント全てに対応するとなると,途方もない記述量となるだろう.

d属性で文字の形を定義する.文法こそpath要素のものと同等だが,glyph要素の持つ座標系はy方向は他の描画要素と異なり,上向きの座標系をとっている.即ち左下が原点となる.これは他のフォント形式での慣例に合わせた仕様である.下記に同じd属性を持つglyph要素とpath要素の例を示す.縦軸の方向が逆となっているため,上下反転しているような結果となる.

1
<svg viewBox="0 0 200 200">
    <defs>
        <font horiz-adv-x="100">
            <font-face units-per-em="100" font-family="pos"/>
            <glyph unicode="1" d="M 0,0 h 100 v 100 z" />
        </font>
    </defs>
    <text font-size="100" font-family="pos" y="150" fill="red">1</text>
    <path d="M 0,0 h 100 v 100 z" transform="translate(100,50)" fill="blue"/>
</svg>

svgの仕様ではこれ以外にも様々な応用が出来ることとなっているが,現状のsvgフォントは必要最低限の動作のみが利用可能である.

unicode
文字形を定義する対象となるユニコード文字.実体参照を使って指定することもできる.
unicode="あ" unicode="&#xe000;"
glyph-name
グリフの名称.単一の文字に複数のグリフを定義する際に利用する.一般的に概念上の文字については複数のグリフを持ちうる.
d
文字の外形線
orientation
文字の方向.横書き(h)・縦書き(v).
arabic-form
アラビア語でのグリフの形式を指定する
lang
言語の指定.
horiz-adv-x
横書きにおける次の文字の基準位置.(文字ごとに異なる場合の設定→プロポーショナルフォント)
vert-adv-y
縦書きにおける次の文字の基準位置.
vert-origin-x
縦書きにおける原点.
vert-origin-y
縦書きにおける原点.

合字の定義

glyph要素で定義できるグリフは単一の文字だけでなく,文字列に対して定義することもできる.この場合,データ上は複数の文字だが表示が単一の文字に見える(合字・リガチャ)こととなる.正しく動作させるには,合字を定義したglyph要素を単一の文字に対応するglyph要素の前に配置する必要がある他,不確定要素が多いためできる事なら使わないほうが良い.

例)<glyph unicode="明治" d="M 0,0 h 1024 v 1024 z" />

合字フォントを設定したdiv要素:明治大正昭和平成

missing-glyph:未定義文字の代替図形

missing-glyph要素はフォントがサポートしない文字が与えられた際の代替図形を定義する.全てのユニコード文字を網羅するフォントというものは現実的でないため,このような機構をとっている.定義の方法はglyph要素と同じである.だが,正しく動作させる例はよく判っていない.

12345
<svg viewBox="0 0 200 200">
    <defs>
        <font horiz-adv-x="100">
            <font-face units-per-em="100" font-family="missing" unicode-range="U+0031-0032"/>
            <glyph unicode="1" d="M 0,0 h 100 v 100 z"/>
            <missing-glyph d="M 0,0 v 100 h 100 z"/>
        </font>
    </defs>
    <text font-size="30" font-family="missing" y="30" fill="red">12345</text>
</svg>

h-kern,v-kern:カーニングの定義

カーニングとは特定の文字対についてその文字間隔を調整して見栄えを保つ事を指す.例えば「V」と「a」をつなげると「Va」となり,注意深く見ると文字間隔が若干狭まって配置されている事が判る(これをカーニング対と呼ぶ).h-kernは横方向の,v-kernは縦方向のカーニング処理を定義する.

u1
カーニング対の前となりうる文字
g1
カーニング対の前となりうるグリフの集合(glyph-name属性を参照する)
u2
カーニング対の後となりうる文字
g2
カーニング対の後となりうるグリフの集合(glyph-name属性を参照する)
k
カーニング対の間隔調整の量.正の値を指定すると間隔が狭まり,負の値を指定すると広がる.
12345 12345
<svg viewBox="0 0 200 200">
    <defs>
        <font horiz-adv-x="1024">
            <font-face units-per-em="1024" font-family="normal"/>
            <glyph unicode="1" d="M 0,0 h 1024 v 1024 z" />
            <glyph unicode="2" d="M 0,0 v 1024 h 1024 z" />
            <glyph unicode="3" d="M 0,0 l 1024,1024 v -1024 l -1024,1024 z"/>
            <glyph unicode="4" d="M 0,0 l 1024,1024 h -1024 l 1024,-1024 z"/>
        </font>
        <font horiz-adv-x="1024">
            <font-face units-per-em="1024" font-family="kerning"/>
            <glyph unicode="1" d="M 0,0 h 1024 v 1024 z" />
            <glyph unicode="2" d="M 0,0 v 1024 h 1024 z" />
            <glyph unicode="3" d="M 0,0 l 1024,1024 v -1024 l -1024,1024 z"/>
            <glyph unicode="4" d="M 0,0 l 1024,1024 h -1024 l 1024,-1024 z"/>
            <hkern u1="1" u2="2" k="500"/>
            <hkern u1="3" u2="4" k="-500"/>
        </font>
    </defs>
    <text font-size="30" font-family="normal" y="30">12345</text>
    <text font-size="30" font-family="kerning" y="60">12345</text>
</svg>
12345 12345
<svg viewBox="0 0 200 200">
    <defs>
        <font vert-adv-y="1024">
            <font-face units-per-em="1024" font-family="normalv"/>
            <glyph unicode="1" d="M 0,0 h 1024 v 1024 z" />
            <glyph unicode="2" d="M 0,0 v 1024 h 1024 z" />
            <glyph unicode="3" d="M 0,0 l 1024,1024 v -1024 l -1024,1024 z"/>
            <glyph unicode="4" d="M 0,0 l 1024,1024 h -1024 l 1024,-1024 z"/>
        </font>
        <font vert-adv-y="1024">
            <font-face units-per-em="1024" font-family="kerningv"/>
            <glyph unicode="1" d="M 0,0 h 1024 v 1024 z" />
            <glyph unicode="2" d="M 0,0 v 1024 h 1024 z" />
            <glyph unicode="3" d="M 0,0 l 1024,1024 v -1024 l -1024,1024 z"/>
            <glyph unicode="4" d="M 0,0 l 1024,1024 h -1024 l 1024,-1024 z"/>
            <vkern u1="1" u2="2" k="500"/>
            <vkern u1="3" u2="4" k="-500"/>
        </font>
    </defs>
    <text font-size="30" font-family="normal" x="30" y="30" writing-mode="tb">12345</text>
    <text font-size="30" font-family="kerning" x="60" y="30" writing-mode="tb">12345</text>
</svg>

font-face:フォント記述の定義

font-face要素はフォント記述と呼ばれるフォントの特性を記述するためのもので,cssにおける@font-faceに相当する機能を有する.

font要素の子要素として定義しそのフォントの特徴を定める他,font-face-src要素と組み合わせて外部フォントをsvg/html文書から利用することが可能となる. 多数の属性が定義されているが,このお陰で他の形式からフォントを変換した際にフォントの設定情報が欠落せずに済む.

属性の分類

font-face要素の属性は,大きく分けて4つ+αのグループフォント選択の為の属性グリフの描画に関わる属性基底線に関わる属性装飾線に関わる属性に分けられる.詳しくはこちらを参照のこと.

フォント選択の為の属性
text要素はこれらの属性を元に描画すべきグリフの形を決定する.つまり,理論上は単一のfont-familyにもこれらの組み合わせの数だけグリフのセットを定義出来るという事になる.
font-family
フォントファミリー名称を設定する.
font-style
フォントのスタイル.all/italic/obliqueの複数指定
font-variant
フォントのスタイル.normal/small-capsの複数指定
font-weight
フォントの太さ.複数指定
font-stretch
フォントの伸縮.複数指定
font-size
フォントの大きさ.
グリフの描画に関わる属性
グリフを描画する際のカンバスに関わる各種情報を定義する.
units-per-em
文字を表示する際のエム平方を描画単位に分割する際の細かさ.大抵はこの1emが他の単位(px等)に割り当てられることで文字の大きさが決定される.他のフォント形式では250(Intellifont), 1000(Type1), 2048(TrueType,TrueType GX,Open-Type)となっている.
stemv
上下ステム幅.
stemh
左右ステム幅.
slope
フォントのストローク角度.
cap-height
大文字グリフの高さ.
accent-height
アクセント図形の原点からの位置.
ascent
文字上端の座標.(原点から文字の上端までの最大距離)
descent
文字下端の座標.(原点から文字の下端までの最大距離)通常マイナス値.
widths
グリフの幅のリスト.
bbox
全てのグリフを欠けること無く描画可能な最小の矩形範囲.
基底線に関わる属性
テキストの整列に関わる属性である.
ideographic
表意文字基底線のオフセット値.
alphabetic
アルファベット基底線のオフセット値.
mathematical
数式基底線のオフセット値.
hanging
吊り下げ基底線のオフセット値.
v-ideographic
表意文字基底線(縦書き)のオフセット値.
v-alphabetic
アルファベット基底線(縦書き)のオフセット値.
v-mathematical
数式基底線(縦書き)のオフセット値.
v-hanging
吊り下げ基底線(縦書き)のオフセット値.
装飾線に関わる属性
文字を線による装飾を行う際のその設定を行う.
underline-position
下線の位置.
underline-thickness
下線の太さ.
strikethrough-position
取り消し線の位置.
strikethrough-thickness
取り消し線の太さ.
overline-position
上線の位置.
overline-thickness
上線の太さ.
unicode-range
ユニコード文字の範囲.
panose-1
書体をを分類する規格「panose-1」の番号を指定する.スペース区切りの10個の数字.欧文フォント用の機構であり,日本語環境ではそれほど意味はない.

font-face-src要素とフォントの参照

font-face要素単体で利用する場合は,下記に示すfont-face-src,font-face-uri,font-face-format,font-face-nameと組み合わせて,外部のフォントを参照することができる.これはCSSにおける@font-faceのsrcの記述に相当する機能で,CSSが動作しない環境でも外部のフォントを参照可能とする為の機構である.従って通常のWEBブラウザでの利用においてはCSSによる記述を使うべきである.

font-face-src要素は外部フォントを参照する際のソースを表す.単体では用いられず,必ず子要素としてfont-face-uri及びfont-face-nameをもつ.

font-face-uri要素は外部フォントへのuri参照を表す.参照先がsvgフォントの場合はxlink:href属性で参照する要素はfont要素でなければならない.更に,フォントの形式を指定する必要がある場合は,子要素としてfont-face-formatを指定する.

font-face-name要素はローカルシステムのフォントを参照するもので,name属性でフォントの名称を指定する.

font-face要素と@font-face規則の互換性

このようにfont-face要素と@font-face規則には仕様上互換があるものの,実際に試してみると機能に差異が存在する.例えば下記は外部woff形式のフォントを読み込ませたものだが,@font-face規則の方は正しく動作しているが,font-face要素の方はそうではない.(もちろん記述上の問題がある可能性は否定できない)

It's web font. It's web font.
<svg>
    <defs>
        <font>
            <font-face font-family="Chela One">
                <font-face-src>
                    <font-face-uri xlink:href="http://themes.googleusercontent.com/static/fonts/chelaone/v1/DHUBEAsCcSRMyWTJ6sisfj8E0i7KZn-EPnyo3HZu7kw.woff">
                        <font-face-format string="woff"/>
                    </font-face-uri>
                </font-face-src>
            </font-face>
        </font>
    </defs>
    <style>
        @font-face {
            font-family: 'Chela One2';
            src: url(http://themes.googleusercontent.com/static/fonts/chelaone/v1/DHUBEAsCcSRMyWTJ6sisfj8E0i7KZn-EPnyo3HZu7kw.woff) format('woff');
        }
    </style>
    <text font-family="Chela One" font-size="35" y="50">It's web font.</text>
    <text font-family="Chela One2" font-size="35" y="150">It's web font.</text>
</svg>

font-face機構を使ったfont-familyの再構成

font-face-src要素で読み込んだフォント情報は,font-face要素及び@font-face規則で定義した内容によって管理される.従って,次に示す例のように異なるフォントを同名のfont-familyで取り扱うと言ったことが可能となる.font-familyプロパティは文書内で頻繁に記述する可能性があり,複雑なフォント設定が必要な場合は一旦font-face機構を使って設定を整理しておくとコードが簡潔となる.

My font-family My font-family My font-family My font-family

フォント自作の実態

svgによるwebフォントの製作は他の形式と比べて容易であるものの,手書きで作るのは現実的ではないだろう.path要素とglyph要素との間でd属性が用いるy座標軸の向きが逆になっていることは前に述べた.この特徴により,path要素で形を確認しそれをglyph要素に変換すると言ったことがやりにくいのだ.従って実際のフォント作成は何らかのスクリプトを記述したりinkscape等のツールを用いることとなるだろう.

use要素とWEBフォントの比較

外部のSVG/フォントファイルで定義された図形を参照すると言った面で,use要素による図形の複製とWEBフォントは似ているが,それぞれどのような特徴を持つのだろうか?以下その比較を行なって見ることとしよう.前提としてhtml文書に図形/グリフを表示するものとする.

比較要素use要素WEBフォント
図形の参照方法 svg要素とuse要素を用いる cssの@font-face, font-familyを用いる
図形に対する識別子の設定 テンプレート図形のid属性に自由に設定可能 unicodeポイントによる指定
スタイルの指定 svgでのスタイル指定 htmlのcssによるスタイル指定
文字列とのスタイルの共通化 塗り潰し色等,一部のみ.(fill=currentColorによるテキスト表示色の共通化) 特に問題なし.
色の指定 複数の色による定義が可能. 現状単色のみ.
図形の参照場所 html内部 html内部,css内部(::before擬似要素,::after擬似要素のcontent)
アニメーション 可能 不可

※クロスドメインでのフォントの利用はhttpレスポンスヘッダー(Access-Control-Allow-Origin)による制御されている.

※この他にもtarget擬似クラスやCSSスプライトを用いた図形の集約があるが,使う側でのスタイル指定が出来ないためここでは省いている.

use要素を用いた図形の複製はSVGの機能をフルに活用できるのが強みで,そのぶん記述が長くSVGとテキストとの境界がはっきりとしている.一方のWEBフォントの場合は特にHTMLファイルを加工する必要なしに図形をシームレスに挿入できる点で有利である.

アイコンフォントとしての利用

SVGフォントに限ったことではないが,アイコンフォントをそのままWEBで利用することはあまり褒められた使い方ではない.というのも,アイコンフォントはフォント機構をベクタ画像の簡易コンテナとして流用しているためで,グリフに割り振られているコードポイントが本来持っている役割(例えばコードポイント「U+0041」であれば「大文字のA」)に無理矢理異なる意味の図形を定義していることになるからだ.これはローカル環境で利用している場合や,何らかの画像に図形として埋め込む場合にはそれほど問題とならない.

だが,WEB環境下でアイコンフォントを利用するとなると問題が顕在化する.アイコンを表示するために挿入された「A」について,webフォントを介さない検索エンジンやスクリーンリーダーなどの環境ではこれが何を意味するのかわからないのだ.その結果,正しくない検索インデックスの生成や,意味のない発音が混入することで音声面でのアクセシビリティの低下等を招くこととなる.

このように文字とグリフとの間に意味合いの違いが存在した場合に問題が発生する.その為,この違いを取り除くことでこの問題は解決するはずだ.つまり次の何れかの方針に従うことで安全にアイコンフォントを利用することが可能となる.


