SVG のデータを TikZ で使う
かなり前に 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}