SVG のデータを TikZ で使う

2025-05-04

かなり前に twitter に投稿したネタです。 おすすめするような内容ではないのですが、一応手順を紹介します。

きっかけ

もともとは、こんな感じでリサイクルマークをプレゼンテーションで使いたいなぁ、と思ったのがきっかけでした。

(テキストの部分は今適当に書いたものなので、気にしないで下さい。 リサイクルマークは https://upload.wikimedia.org/wikipedia/commons/4/44/Recycle001.svg より。)

軽く探してみた範囲ではリサイクルマークを TikZ で書いたものは見当たらず、自分で描くのはさすがに面倒です。 「世の中にはたくさん SVG で書かれたものがあるのだから、これが使えれば楽なのになぁ」と思っていろいろ探した結果、 どうやら TikZ の svg.path ライブラリーで実現できそうだということが分かりました。 ただ、 TikZ のマニュアルを見てもほとんど記述がなく一瞬途方に暮れたのですが、いろいろ試してみたらなんとかできました。

基本的な手順

まず SVG ファイルをダウンロードします。 ここでは上の図で使用した https://upload.wikimedia.org/wikipedia/commons/4/44/Recycle001.svg を例にとります。このファイルの中身は、

<?xml version="1.0" encoding="UTF-8"?>
<svg width="777px" height="733px"
xmlns="http://www.w3.org/2000/svg" version="1.0"
xmlns:xlink="http://www.w3.org/1999/xlink">

<g fill="#009900" stroke="black" stroke-width="10" stroke-linecap="round" stroke-linejoin="round">
<path d="M280 272  C134 187 134 187 134 187  C210 54 210 54 210 54  C231 17 309 16 336 48  C373 110 373 110 373 110z" />
<path d="M162 475  C84 475 84 475 84 475  C54 471.75 4 410 34 354  C68 297 68 297 68 297  C15 266 15 266 15 266  C183 266 183 266 183 266  C268 412 268 412 268 412  C215 383 215 383 215 383z" />
<path d="M363 496  C363 667 363 667 363 667  C176 667 176 667 176 667  C165 668 157 657 151 648  C63 492 64 493 60 488  C64.75 492 70 496 85 496z" />
<path d="M687 496  C706 494 709 489 714 486  C620 652 620 652 620 652  C616 660 608 667 596 667  C492 667 492 667 492 667  C492 728 492 728 492 728  C407 583 407 583 407 583  C492 437 492 437 492 437  C492 496 492 496 492 496z" />
<path d="M519 315  C666 231 666 231 666 231  C743 362 743 362 743 362  C771 416 723 468 691 474  C612 474 612 474 612 474z" />
<path d="M357 35  C351 27 339 17 328 15  C525 15 525 15 525 15  C536 15 546 19 551 28  C602 118 602 118 602 118  C653 89 653 89 653 89  C570 233 570 233 570 233  C404 233 404 233 404 233  C454 203 454 203 454 203z" />
</g>

</svg>

のような感じになっています。 このうち、 path 要素の d 属性、つまり <path d="..." /> のみが必要な部分です。 (d 属性については例えば d - SVG: スケーラブルベクターグラフィック | MDN などを参照して下さい。)

この中身を、

% \usepackage{tikz}
% \usetikzlibrary{svg.path}

\begin{tikzpicture}
  \draw
  svg[yscale=-1] {
    % ここに SVG の <path d="..." /> の中身をコピー & ペーストする
  };
\end{tikzpicture}

に書いてやればできあがりです (\usetikzlibrary{svg.path} が必要です)。 具体的には、

% \usepackage{tikz}
% \usetikzlibrary{svg.path}

\begin{tikzpicture}
  \draw
  svg[yscale=-1] {
    M280 272  C134 187 134 187 134 187  C210 54 210 54 210 54  C231 17 309 16 336 48  C373 110 373 110 373 110z
    M162 475  C84 475 84 475 84 475  C54 471.75 4 410 34 354  C68 297 68 297 68 297  C15 266 15 266 15 266  C183 266 183 266 183 266  C268 412 268 412 268 412  C215 383 215 383 215 383z
    M363 496  C363 667 363 667 363 667  C176 667 176 667 176 667  C165 668 157 657 151 648  C63 492 64 493 60 488  C64.75 492 70 496 85 496z
    M687 496  C706 494 709 489 714 486  C620 652 620 652 620 652  C616 660 608 667 596 667  C492 667 492 667 492 667  C492 728 492 728 492 728  C407 583 407 583 407 583  C492 437 492 437 492 437  C492 496 492 496 492 496z
    M519 315  C666 231 666 231 666 231  C743 362 743 362 743 362  C771 416 723 468 691 474  C612 474 612 474 612 474z
    M357 35  C351 27 339 17 328 15  C525 15 525 15 525 15  C536 15 546 19 551 28  C602 118 602 118 602 118  C653 89 653 89 653 89  C570 233 570 233 570 233  C404 233 404 233 404 233  C454 203 454 203 454 203z
  };
\end{tikzpicture}

のようになります。簡単ですね。

より忠実にオリジナルを再現したい場合は、

\definecolor{bgcol}{HTML}{009900} % 背景色を定義

\begin{tikzpicture}
  %     ↓ draw のオプションを追加
  \draw[fill=bgcol, color=black, line width=10, line cap=round, line join=round]
  svg[yscale=-1] {
    (略)
  };
\end{tikzpicture}

のように、(上の SVG ファイルの場合は) g 要素の属性を反映させると良いでしょう。

それぞれの結果は次のようになります。

この方法の問題点

ところで SVG ファイルによってはこのままでは上手くいかない場合があります。

というか、基本的に複雑な SVG ファイルだとうまくいきません。 例えば、 <g> 要素で座標変換が適用されているなどの場合は、そのままでは上手くいかないでしょう。

また、 SVG ファイルによっては、単にコピペしただけだと、

Dimension too large.

というエラーが出る場合があります。 例えば https://d-maps.com/m/asia/japan/japon/japon04.svg から取得した SVG ファイルでそのようになります。 SVG での値は pt 単位として扱われるので、 \maxdimen (16383.99998 pt) を越える値が使用されているとこのエラーが発生します。 この場合は SVG 内に出てくる座標値を縮小する必要があります。 例えば、次のようにできます。

perl -ne 'if(/\bd="([^"]+)"/){($d=$1)=~s/([A-Za-z]?)(-?\d+\.?\d*)?/"$1".(($2 eq "")?$2:$2*0.01)/ge;print "$d\n"}' file > outfile

ただし、この方法では、

  • d=" ... " の途中に改行が入っているとうまくいかない
  • A, a コマンド (楕円) が使われていると破綻する

などの問題があります。

まとめ

いろいろ書いてきましたが、余計なことをしないで実直な方法を使用するのが良いと思います。

SVG ファイルを使用したい場合は inkscape や ImageMagick 等で PDF に変換し、それを \includegraphics などを使用して取り込むのが無難でしょう。

最初に挙げた図も、リサイクルマークを入れることで分かりやすくなっているかといえば微妙な気がしますし、 文字と図が重なっている時点で視認性が下がっている気もします。 リサイクルマークを入れるにしても、わざわざ背景に入れるなどという凝ったことをしなくても、

のような感じの方が見易さ的にも図の作成の手間的にもずっと良い気がします。

ちなみにこの図は、

magick Recycle001.svg Recycle001.pdf

Recycle001.pdf を生成した上で、以下のコードで作成しました。

% \usepackage{graphicx}
% \usepackage[most]{tcolorbox}

\tcbsidebyside[sidebyside adapt=left, sidebyside gap=0.5em,
  width=22em, left=1ex, colback=white, segmentation empty]
{
  \includegraphics[width=3em]{Recycle001.pdf}
}
{
  \centering
  \bfseries
  関数: 同じ処理を何度も書かずにすむ \\[1ex]
  $\Rightarrow$ 処理を再利用できる
}

参考

最初の図は、以下のコードで作成しました。 外部ファイルが不要になるので、これはこれですっきりしていて個人的には好きなのですが。

% \usepackage[most]{tcolorbox}
% \usetikzlibrary{svg.path}

\begin{tcolorbox}[width=19em, colback=white, enhanced, halign=center,
  watermark tikz={
    \draw[use as bounding box,  line width=2pt, color=green!50, fill=green!20]
    svg[yscale=-1, yshift=-5cm] {
      M280 272  C134 187 134 187 134 187  C210 54 210 54 210 54  C231 17 309 16 336 48  C373 110 373 110 373 110z
      M162 475  C84 475 84 475 84 475  C54 471.75 4 410 34 354  C68 297 68 297 68 297  C15 266 15 266 15 266  C183 266 183 266 183 266  C268 412 268 412 268 412  C215 383 215 383 215 383z
      M363 496  C363 667 363 667 363 667  C176 667 176 667 176 667  C165 668 157 657 151 648  C63 492 64 493 60 488  C64.75 492 70 496 85 496z
      M687 496  C706 494 709 489 714 486  C620 652 620 652 620 652  C616 660 608 667 596 667  C492 667 492 667 492 667  C492 728 492 728 492 728  C407 583 407 583 407 583  C492 437 492 437 492 437  C492 496 492 496 492 496z
      M519 315  C666 231 666 231 666 231  C743 362 743 362 743 362  C771 416 723 468 691 474  C612 474 612 474 612 474z
      M357 35  C351 27 339 17 328 15  C525 15 525 15 525 15  C536 15 546 19 551 28  C602 118 602 118 602 118  C653 89 653 89 653 89  C570 233 570 233 570 233  C404 233 404 233 404 233  C454 203 454 203 454 203z
    };
  }]

  \bfseries
  関数: 同じ処理を何度も書かずにすむ \\[1ex]
  $\Rightarrow$ 処理を再利用できる
\end{tcolorbox}