しかたらむーの てっくぶろ

組み込みソフトの古参エンジニアがモダンなフロントエンドエンジニアに転生 その進化の記録です

Inkscape で自前のSVGアイコンを作ってみる

はじめに

前回はInkscapeを使って自前のアイコンを作り、Webアプリで表示、イベントをハンドリングする記事を書きました。これらの記事では、PNG形式の画像データを使ったアイコンだったので拡大するとギザギザして見栄えに課題がありました。

techblo.shikataramuno.com

techblo.shikataramuno.com

SVG形式のアイコンにすれば拡大しても見栄えは変わりません。
今回はInkscapeを使ってSVGアイコンを作る手法を紹介します。

SVGとは

SVGとはScalable Vector Graphicsと言うベクター形式で拡縮自在なグラフィックスを実現するXMLベースの画像形式です。 詳しくはこちら Scalable Vector Graphics - Wikipedia

InkscapeXMLエディター

では、Inkscapeを使ってSVGアイコンを作ってみます。Inkscapeはもともと描画データをSVG形式で扱うので簡単にSVG形式の図形データを作れます。ですが、思い通りにアイコンのデータを作るには少しコツが必要です。
まずは簡単な矩形を描いてみましょう。こんな感じです。

f:id:Shikataramuno:20190204103612p:plain

この図形のSVGデータはメニューバーの「編集」ー>「XMLエディター」を選択すると確認できます。こんな感じです。

f:id:Shikataramuno:20190204104504p:plain

ノードのツリー構造が表示され、各ノードを選択するとその属性値が右側に表示されます。このまま保存して必要な部分(上の例では rect6161ノード)を使えばよさそうなのですが、実はこのままではうまく表示されません。

transformの影響

rectノードのxy座標がlayerノードの属性transformの影響を受け、レイヤー内の座標系に変換された値になってしまうからです。アイコンとして表示した際に表示領域外になってしまい、思った位置にうまく表示されません。以下の様にずれた位置に表示されたり、まったく表示されなかったりとなかなか思った通りに表示されなくなってしまいます。

f:id:Shikataramuno:20190204113030p:plain

Inkscapeでは、新規作成で作図するときにデフォルトのlayerノード下に図形データが配置されてしまいます。この状態でマウスのドラッグ&ドロップで図形を移動させたり、マウスで頂点をドラッグ&ドロップして拡大・縮小したりするとlayerノードの属性にtransformが追加され図形のxy属性値がこの影響を受け座標変換後の値になってしまいます。アイコンとしてうまく表示させるにはこの座標変換の影響を排除する必要があります。

f:id:Shikataramuno:20190204110334p:plain

では実際に試してみましょう。
メニューバーの「ファイル」ー>「新規(N)」で新たなドキュメントを開いてください。何も描画していないところで矩形を描いて、XMLエディターでSVGドキュメントを確認してみてください。上述の様に、layerノードの下にrectノードが作成されていると思います。次にlayerノードを選択してみてください。この段階ではまだtransform要素は追加されていません。

f:id:Shikataramuno:20190204105841p:plain

この状態でキャンバス上のrectを選択しマウスで移動させてみてください。layerのノードにtransform要素が追加されると思います。これ以降、rectノードの属性値がtransformの影響を受けるようになってしまいます。

f:id:Shikataramuno:20190204110334p:plain

transformの影響を排除

transformの影響をなくすには、XMLエディターでrectノードをドラッグ&ドロップしルート直下の位置に移動させます。そうすることでrectノードの属性値がlayerノードの影響を受けなくなります。常に描画領域の左上を原点とた絶対座標系で表される様になり、アイコンとして表示させる場合と合致し扱いやすくなります。

f:id:Shikataramuno:20190204111315p:plain

図形データを切り出す

transformの影響を排除し、XMLエディタで属性値を適切な値(サイズ、位置)に調整した後(縦横が18pxくらいがアイコンとしてちょうどよいサイズかもしれません)、メニューバーの「ファイル」ー>「名前を付けて保存」を実行すればアイコンデータが出来上がります。

保存したsvgファイルのアイコンに該当するノード(今回の場合 rectノード)を切り出せばSVG形式のアイコンとして使えるデータになります。以下はInkscapeで保存したsvg形式のファイルです。51行目~59行目のrectノードがアイコンとして使う部分に該当します。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="210mm"
   height="297mm"
   viewBox="0 0 210 297"
   version="1.1"
   id="svg6169"
   inkscape:version="0.92.1 r15371"
   sodipodi:docname="SVGアイコンを作ってみる.svg">
  <defs
     id="defs6163" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.35"
     inkscape:cx="396.5998"
     inkscape:cy="560"
     inkscape:document-units="mm"
     inkscape:current-layer="svg6169"
     showgrid="false"
     inkscape:window-width="1009"
     inkscape:window-height="671"
     inkscape:window-x="283"
     inkscape:window-y="33"
     inkscape:window-maximized="0" />
  <metadata
     id="metadata6166">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <rect
     style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:0.52916664;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
     id="rect6714"
     width="18"
     height="18"
     x="0"
     y="0"
     rx="2"
     ry="2" />
  <g
     inkscape:label="レイヤー 1"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(0,25.702381)" />
</svg>

謝辞

最後まで読んでくださいありがとうございます。初めてSVGアイコンを表示させたとき、何も表示されなくて、何が原因なのか皆目わからずに結構はまってしまいました。この記事の内容が何かのお役たてれば幸いです。次回は、この方法で作成したSVGアイコンをVue + Typescriptで操作していみたいと思います。