SVGは入門のハードルは低いが、門から先が長い。長いというか、道の枝分かれがすごい。本筋となる知識を固めるべく、主にMDNのSVGの項を参考に、基本的なSVG要素(と属性値)の使い方ををまとめる。

コンテナ系のSVG要素

HTMLドキュメントが<html>タグで始まるように、SVGドキュメントは<svg>タグで始まる。ただ<html>と違い、<svg>タグは入れ子にできる。

複数の要素をまとめるためのタグとしては、他に<g>タグもある。こちらも入れ子で使うことができる。

<svg>タグは、個々に座標系とビューポート(表示領域)を持つ。一方<g>タグは<svg>タグに含まれ、その座標系とビューポートに従って描画される。

ちなみに、<html>タグには枠線と背景色を指定できるが、<svg>タグには枠線も背景色も指定できない。

html
<p>SVGタグは空っぽの領域を確保するだけ。色も背景色もない。学校も試験もない。</p>
<svg width="30px" height="30px" fill="gray"></svg>
<p>👆ここにsvgタグがいる</p>

画像単位のコンテナ

<svg>タグを使う。これがSVGのルート要素となる。

指定できる主な属性値 概要
width SVG要素の幅。使える単位は、CSSプロパティと同じ。数値のみを指定すると、ピクセル単位として解釈される。
height SVG要素の高さ。
x 外側にSVG要素がある場合の、x軸の相対位置。
y 外側にSVG要素がある場合の、y軸の相対位置。
viewBox widthとheightに指定したサイズとは別に、SVGオブジェクトの描画領域を4つの値(min-x、min-y、width、height)で指定する。
顕微鏡で言えば、widthheightが覗くところのサイズで、viewBoxが標本(描画内容)の位置とかレンズの倍率を調整するところ、みたいなイメージ。
描画領域のサイズが覗き穴に対して小さいほど拡大され、大きいほど縮小される。
preserveAspectRatio 親要素の中で、SVGがどのようなアスペクト比で描画されるかを指定する。指定できる値はこちらから参照できる。

要素単位のコンテナ

<g>タグを使う。gはgroupの略。<svg>タグと似ているが、<g>タグに指定した属性値は子要素にも適用される。

図形描画系のSVG要素

SVGには、基本的な図形(シェイプ)を扱うタグが用意されている。同じ画像を異なるタグを使って描画することもできる。例えば四角形を描画するためには四角形のシェイプを使うのが早道だが、線を繋いで形にしても良い。

各図形に共通する属性

属性名 概要
fill 領域を塗りつぶす色。RGB、HEX、RGBA、HSL、HSLAなどのほか、色の名前でも指定できる。デフォルトはblack
fill-opacity 塗りつぶしの透明度。完全な透明が0で、完全な不透明が1。デフォルトは1
stroke 線の色。デフォルトはnone
stroke-opacity 線の透明度。デフォルトは1
stroke-width 線の幅。デフォルトは1
stroke-dasharray 破線のパターンを指定。stroke-dasharray="破線の長さ,空白の長さという形。デフォルトはnone
stroke-linecap 線の終端の形状。
butt:線と同時に直角に終わる(デフォルト)
round:線の終端から半円で終わる
square:線の終端から、線の幅の半分だけ出て直角で終わる
デフォルトはbutt
stroke-linejoin 2つの線のつなぎめの形状。
miter:直角(デフォルト)
round:丸
bevel:斜角
デフォルトはmiter

引用元:Fills and Strokes – SVG: Scalable Vector Graphics | MDN

ちなみにストロークの幅(stroke-widthに指定した値)は、その中心が座標と対応する。例えば垂直の線をx="0の座標に置くと、線が半分に切れてしまう。

html
<svg width="100" height="100">
  <line x1="0" y1="0" x2="0" y2="100" stroke="black" stroke-width="10" />
  <line x1="50" y1="0" x2="50" y2="100" stroke="black" stroke-width="10" />
  <line x1="100" y1="0" x2="100" y2="100" stroke="black" stroke-width="10" />
</svg>

全体を表示させるには、図形の座標を調整するなり、viewBoxの値を調整するなりする必要がある。注意が必要である。

html
<svg width="100" height="100">
  <line x1="5" y1="0" x2="5" y2="100" stroke="black" stroke-width="10" />
  <line x1="50" y1="0" x2="50" y2="100" stroke="black" stroke-width="10" />
  <line x1="95" y1="0" x2="95" y2="100" stroke="black" stroke-width="10" />
</svg>

四角形

<rect>タグを使う。

指定できる属性値 概要
x 右上のx座標。
y 右上のy座標。
width 幅。
height 高さ。
rx 角を丸めたいときのx軸の半径。
ry 角を丸めたいときのy軸の半径。

角丸を扱う場合、以下の点に注意が必要である。

  • 角丸は、横の半径がrx、縦の半径がryの円の境界に沿った形で表現される。
  • rx,ryは、各角と円の中心点の距離とも言える。
  • rx,ryを片方だけ指定すると、両者に同じ値が設定される。
  • rx,ryを省略したり、0以下の値を指定すると、無視される。
  • rx,ryの最大値は、それぞれ矩形の幅・高さの半分となる。
html
<svg width="100" height="100">
  <rect x="0" y="0" width="100" height="100" rx="5" ry="5" fill="gold" />
</svg>

真円

circleタグを使う。

指定できる属性値 概要
r radiusの略。円の半径。
cx center xの略。円の中心のx座標。
cy center yの略。円の中心のy座標。
html
<svg width="100" height="100">
  <circle r="50" cx="50" cy="50" fill="gold" />
</svg>

楕円

<ellipse>タグを使う。

指定できる属性値 概要
cx 円の中心のx座標。
cy 円の中心のy座標。
rx 横の半径。
ry 縦の半径。
pathLength パスの長さ。デフォルトはnone(ぜんぶ描画)。
html
<svg width="100" height="100">
  <ellipse rx="50" ry="25" cx="50" cy="50" fill="gold" />
</svg>

直線

<line>タグを使う。

指定できる属性値 概要
x1 始点のx座標。
y1 始点のy座標。
x2 終点のx座標。
y2 終点のy座標。
html
<svg width="100" height="100">
  <line x1="25" y1="50" x2="75" y2="50" stroke="gold" stroke-width="3"/>
</svg>

折れ線

<polyline>タグを使う。

指定できる属性値 概要
points 座標の配列。カンマ区切り、空白区切り、改行区切りが使える。
ただしいずれかに統一するとスーパーわかりにくいので、
xとyの間はカンマ、各座標は空白区切り、などとすると良いと思う。
html
<svg width="100" height="100">
  <polyline points="1.5,75 25,25 50,75 75,25 98.5,75" stroke="gold" stroke-width="3" fill="none" />
</svg>

多角形

<polygon>タグを使う。<polyline>タグとほぼ同じだが、最後の点は自動的に始点と繋がる。

指定できる属性値 概要
points <polyline>と同じ。
html
<svg width="100" height="100">
  <polygon points="1.5,75 25,25 50,75 75,25 97,75 50,98.5 3,75" stroke="gold" stroke-width="3" fill="none" />
</svg>

パス(何でも描け〜る)

<path>タグを使う。

指定できる属性値 概要
d "data path"の略。詳細はSVGのpathタグで使う属性値のチートシート別途にまとめる。

グラデーション系のSVG要素

CSSと同様、SVGにもグラデーション用の仕組みがある。線形グラデーションと円形グラデーションである。これらは、以下の手順でシェイプのfill、あるいはstrokeに適用できる。

  1. <svg>タグ内に<defs>タグを使ってグラデーションの色と位置を定義する(グラデーションには識別できるidを付ける)。
  2. 各シェイプのfill属性、あるいはstroke属性に、適用するグラデーションのidを指定する。

定義と適用場所が離れている点が特徴的と言える。例えば、以下は線形グラデーションの簡単なサンプルである。

html
<svg width="200" height="200">
  <defs>
    <linearGradient id="linearGradient">
      <stop class="stop1" stop-color="black" offset="0%" />
      <stop class="stop2" stop-color="gray" offset="50%" />
      <stop class="stop3" stop-color="white" offset="100%" />
    </linearGradient>
  </defs>
   <rect fill="url(#linearGradient)" x="10" y="0" width="200" height="40" />
   <circle r="50" cx="50" cy="100" fill="url(#linearGradient)" />
</svg>

線形グラデーション

先述の通り、線形グラデーションの定義には<linearGradient>タグを使う(<linearGradient>タグの子要素として使っている<stop>タグの説明は後述する)。

指定できる属性値 概要
x1 グラデーションの開始点のx座標。
デフォルト値は0
y1 グラデーションの開始点のy座標。
デフォルト値は0
x2 グラデーションの終了点のx座標。
デフォルト値は0
y2 グラデーションの終了点のy座標。
デフォルト値は0
href 他の<linearGradient>タグの定義を継承する。
指定する値は該当のタグのid。デフォルト値はnone
gradientUnits グラデーションの座標指定に使う座標系を指定する。
userSpaceOnUse:ルートSVGの矩形
objectBoundingBox:シェイプを囲う最小限の矩形
デフォルトはobjectBoundingBox
gradientTransform グラデーションを変形する。
過去の遺産で、働きは各要素共通属性のtransformと同じ。
spreadMethod (x1,y1)(x2,y2)で指定したサイズより先に、
グラデーションがどう広がるかを指定(グラデーションのサイズがシェイプのサイズより小さい時によくわかる)。
pad: 終了点の色を拡張する。
reflect: 境界部分で反射(始点含む)させ、スムーズに繰り返す。
repeat: 開始点・終了点をブツ切りで繰り返す。

一見わかりづらいが、グラデーションの角度は(x1, y1)(x2, y2)の2点を結ぶ直線の角度として指定できる。

いろいろむつかしい。spreadMethod属性とか説明できている気がしない。参考までに、MDNからspreadMethod属性のサンプルを流用する。

html
<svg width="220" height="150" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="PadGradient" x1="33%" x2="67%">
      <stop offset="0%" stop-color="fuchsia" />
      <stop offset="100%" stop-color="orange" />
    </linearGradient>
    <linearGradient id="ReflectGradient" spreadMethod="reflect" x1="33%" x2="67%">
      <stop offset="0%" stop-color="fuchsia" />
      <stop offset="100%" stop-color="orange" />
    </linearGradient>
    <linearGradient id="RepeatGradient" spreadMethod="repeat" x1="33%" x2="67%">
      <stop offset="0%" stop-color="fuchsia" />
      <stop offset="100%" stop-color="orange" />
    </linearGradient>
  </defs>

  <rect fill="url(#PadGradient)" x="10" y="0" width="200" height="40" />
  <rect fill="url(#ReflectGradient)" x="10" y="50" width="200" height="40" />
  <rect fill="url(#RepeatGradient)" x="10" y="100" width="200" height="40" />

  <line x1="34%" y1="0" x2="34%" y2="140" stroke="black" stroke-width="2" stroke-dasharray="5 3"/>
  <line x1="66%" y1="0" x2="66%" y2="140" stroke="black" stroke-width="2" stroke-dasharray="5 3"/>
</svg>

参考元:spreadMethod – SVG: Scalable Vector Graphics | MDN

破線の部分は、わかりやすさのためにこちらで足した。破線と破線の間が定義したグラデーションの範囲で、これをはみ出た部分の部分の広がり方をspreadMethod属性で指定している。

放射形グラデーション

放射形グラデーションの定義には<radialGradient>タグを使う。

指定できる属性値 概要
cx "Center X"の略。グラデーションが終了する円の、中心点のX座標。
デフォルトは50%
cy "Center Y" の略。終了円の中心点のY座標。
デフォルトは50%
r "Radius"の略。終了円の半径。
デフォルトは50%
fx "Focal Point X"の略。開始円(グラデーションの光源)の中心点のX座標。
デフォルトはcxを継承。
fx "Focal Point Y"の略。開始円の中心点のY座標。
デフォルトはcyを継承。
fr "Radius of the focal circle"の略。
デフォルトは0%
href <radialGradient>タグと同じ。
gradientUnits <radialGradient>タグと同じ。
gradientTransform <radialGradient>タグと同じ。
spreadMethod <radialGradient>タグと同じ。

<linearGradient>の項で使わなかったhref属性を使いサンプルを示す。

html
<svg width="200" height="100">
<defs>
    <radialGradient id="radialParent" cx="0%" cy="0%" r="100%">
      <stop offset="28%" stop-color="white" />
      <stop offset="32%" stop-color="darkgray" />
      <stop offset="46%" stop-color="lightgray" />
      <stop offset="60%" stop-color="gray" />
      <stop offset="74%" stop-color="lightgray" />
      <stop offset="88%" stop-color="darkgray" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
  <radialGradient id="radialChild" href="#radialParent">
      <stop offset="0%" stop-color="black" />
      <stop offset="50%" stop-color="gold" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
  </defs>
    <rect fill="url(#radialParent)" x="0" y="0" width="100" height="100"/>
    <rect fill="url(#radialChild)" x="101" y="0" width="99" height="100"/>
</svg>

r=100%としているのは、終了円の中心点を原点に指定したことで、デフォルト値(50%)のままだとグラデーションの領域が4分の1になってしまうためである。

href属性で継承されるのは<radialGradient>タグの属性値のみで、子要素の<stop>タグについてはそれぞれ指定する必要がある。

グラデーションの色と位置

グラデーションの色と位置は、<stop>タグを用いて定義する。

指定できる属性値 概要
offset 色の終了位置。数値あるいはパーセンテージを指定する。
デフォルトは0
stop-color 終了位置の色 。
デフォルトはblack
stop-opacity 終了位置の不透明度。0-1の間で指定。
デフォルトは1
html
<svg width="200" height="100">
<defs>
  <radialGradient id="stopSample1">
      <stop offset="0%" stop-color="black" />
      <stop offset="50%" stop-color="gold" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
      <radialGradient id="stopSample2">
      <stop offset="0%" stop-color="black" />
      <stop offset="50%" stop-color="gold" />
      <!-- 👆ONAJI!👇 -->
      <stop offset="50%" stop-color="black" />
      <stop offset="100%" stop-color="black" />
    </radialGradient>
  </defs>

    <rect fill="url(#stopSample1)" x="0" y="0" width="100" height="100"/>
    <rect fill="url(#stopSample2)" x="101" y="0" width="99" height="100"/>
</svg>

offset属性の値が同じ<stop>タグがあると、右側のようにグラデーションがスパッと終わる。

テキスト系のSVG要素

svgタグの中でテキストを表示するには、<text>タグを使う。裸のテキストを入れると無視されるため注意。

指定できる属性値 概要
x テキストのX座標。
デフォルトは0
y テキストのY座標。
デフォルトは0
dx xに指定した座標からの相対位置。
カンマ区切り、あるいは空白区切りで文字単位のX座標を指定できる。
デフォルトはnone
dy yに指定した座標からの相対位置。
カンマ区切り、あるいは空白区切りで文字単位のX座標を指定できる。
デフォルトはnone
text-anchor x属性、y属性で指定した座標に、テキストのどの部位を持ってくるかを指定。
start:テキストの始端が指定座標に来る。
middle:テキストの中央が指定座標に来る。
end:テキストの終端が指定座標に来る。
デフォルトはstart
rotate 文字の角度。
1つだけ与えると全文字に適用され、カンマ区切り、あるいは空白区切りで文字単位の角度を指定できる。
文字数より少ない数を与えると、最後の角度が残りの全文字に適用される。
デフォルトはnone
textLength 最初の文字と最後の文字の幅。文字を等間隔に配置したい場合などに使う。
テキストを拡大・縮小させるためのものではないので注意。
デフォルトはなし(ブラウザが計算した値)。
lengthAdjust textLengthの範囲に収めるための調整方法を指定。
spacing:文字間隔で調整。
spacingAndGlyphs:文字間隔と文字サイズで調整。
デフォルトはspacing
html
<svg width="200" height="100">
  <text font-size="40" fill="gold" stroke="black"
        x="50%" y="50%"
        text-anchor="middle"
        dx="4 4"
        dy="0,0,10,15,-25"
        rotate="-10 -10 10"
        textLength="200"
        lengthAdjust="spacingAndGlyphs">
    Hello, svg.
  </text>
  <circle r="5" cx="50%" cy="50%" fill="gray" />
  <rect x="0" y="0" width="200" height="100" fill="none" stroke="black" />
  <line x1="50%" y1="0" x2="50%" y2="100%" stroke="gray" stroke-dasharray="5 5" />
  <line x1="0" y1="50%" x2="100%" y2="50%" stroke="gray" stroke-dasharray="5 5" />
</svg>

上のサンプルは、ビューポートの幅が200pxに対して、文字サイズが50pxある。そのまま表示すると、文字列がビューポートからはみ出る。textLengthを使うと、こういった場合に文字の表示領域を制限できる。文字の間隔を調整するか、文字のサイズと間隔を両方調整するかは、lengthAdjust属性で指定する。

また、dxdyに複数の値を指定する場合、最初の値以外は、直前の値からの相対位置になる。

参考資料