SVGの基礎 2

ここからは少し高度な使い方を学ぶ。

パス path

パス(path)は複数の直線や曲線を組み合わせて複雑な図形を記述するときに用いる。

<svg width="100" height="60" style="background-color:white; xmlns="http://www.w3.org/2000/svg">
    <path d="M20,30 Q40,5 50,30 T90,30" fill="none" stroke="blue" stroke-width="5" />
</svg>

上記を記述すると、以下のように表示される。

パス要素(path element)は以下のような記述から開始される。
    <path d="
このように、d属性で記述が始まる。

直線コマンド

全部で5個のコマンドがある。 大文字コマンドの x y はSVGキャンパスの絶対座標を示し、小文字コマンドは相対座標を示す。

コマンド解説
M x y または m dx dyMove toの略で、座標の開始位置を指定するときに使用する。
L x y または l dx dyLine toの略で、直前の座標から指定座標に直線を引く。
H x または h dx水平線を指定されたx座標へ引く。または、dxのサイズ分だけ引く。
V y または v dy垂直線を指定されたy座標へ引く。または、dyのサイズ分だけ引く。
Z または z始点と最後の点を結んで線を引き、閉じた図形にする。

それでは、以下のように図形を書いてみる。

<svg width="120" height="110" xmlns="http://www.w3.org/2000/svg">
    <path d="M10,10 h 90 v 90 H 10 Z" fill="none" stroke="blue" stroke-width="5" />
</svg>

曲線コマンド

曲線コマンドは3種類ある。2つは3次ベジェ曲線と2次ベジェ曲線、3つ目は円弧である。

ベジェ曲線

コマンド解説
C x1 y1, x2 y2, x y
または
c dx1 dy1, dx2 dy2, dx dy
3次元ベジェ曲線を直前の座標からx y へ描く。
x1 y1は直前の座標の制御点、x2 y2は終点の制御点。
S x2 y2, x y
または
s dx2 dy2, dx dy
3次元ベジェ曲線を直前の座標からx y へ描く。
x1 y1は直前の座標の制御点の反対方向を流用し、
滑らかに曲線を繋ぐ。
x2 y2は終点の制御点。
直前がC,S以外の場合、Qコマンドと見なされる。
Q x1 y1, x y
または
q dx1 dy1, dx dy
2次元ベジェ曲線を直前の座標からx y へ描く。
x1 y1は制御点。
T x y
または
t dx dy
2次元ベジェ曲線を直前の座標からx y へ描く。
制御点は直前のQ,Tコマンドの反対方向を使う。
直前がQ,Tコマンド以外の場合、単なる直線になる。

3次元ベジェ曲線の例

CとSの組み合わせで

<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
    <path d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"
        fill="none" stroke="black" />
</svg>

と描写すると、

制御点を表示すると、

どの位置に制御点があるのかわかる。 しかし、実際の運用で制御点を決めるのは難しいので、InkScapeなどのベジェ曲線を利用するとよい。

2次元ベジェ曲線の例

同じような図形は2次元ベジェ曲線でも記述できる。 この場合、QとTの組み合わせになる。

<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
    <path d="M 10 80 Q 52.5 10, 95 80 T 180 80"
        fill="none" stroke="black" />
</svg>

制御点を表示すると、

3次元ベジェとどちらが良いかは、図形の対称性の問題であり、場合による。 2次元ベジェで記述できない場合、3次元ベジェで記述できるだろう。 細かく刻めばどのような図形も書けるだろうが、 極力、効率よく記述すればデータ量削減と描画速度が速くなる。

円弧

円弧はかなり多くの引数を取り、

A rx ry x-axis-rotation large-arc-flag sweep-flag x y
a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy

で表現される。

円弧は結構難しい。始点と終点を結ぶ円弧を描くが、楕円のX方向半径 rx とY方向半径 ry を指定するようになっている。 始点と終点(x y 又は dx dy)を含む円弧がピッタリ合うように、楕円の位置を上下にずらして位置合わせを自動的に行なう。 終点の座標が遠ければ、楕円の形はそのままで自動的に拡大し、最小サイズの楕円が選択される。

<svg width="360" height="100" xmlns="http://www.w3.org/2000/svg">
    <path d="M 30 80 a 30 50 0 0 1 40 0" stroke="black" fill="green" />
    <path d="M 80 80 a 30 50 0 0 1 50 0" stroke="black" fill="green" />
    <path d="M 140 80 a 30 50 0 0 1 60 0" stroke="black" fill="green" />
    <path d="M 220 80 a 30 50 0 0 1 90 0" stroke="black" fill="green" />
</svg>

を記述すると、

のように表示される。 4つの円弧はすべて同じ rx=30 ry=50 を指定しているので、同じ形の楕円を表している。 終点の位置はX軸方向のサイズで指定しており、dx=40,50,60,90となっている。 Y座標はすべてdy=0で、始点と終点のY座標は同じ位置になっている。 楕円の横幅は30×2=60なので、dx≦60の場合、指定サイズの楕円の始点と終点が一致する円弧が選ばれている。 しかし、dx=90の場合は一致点が無いので、楕円を拡大して一致する楕円の中で最小の楕円が選択されている。 この場合、一致する楕円はちょうど楕円の上半分になり、端点を通る線分は楕円の中心を通っている。 上半分より上の円弧を選択するように考えてみると、さらに大きな楕円を選択することになるので、 その意味がわかるだろう。

それでは、楕円の角度を指定してみる。

<svg width="360" height="100" xmlns="http://www.w3.org/2000/svg">
    <path d="M 30 80 a 30 50 40 0 1 40 0" stroke="black" fill="green" />
    <path d="M 80 80 a 30 50 40 0 1 50 0" stroke="black" fill="green" />
    <path d="M 140 80 a 30 50 40 0 1 60 0" stroke="black" fill="green" />
    <path d="M 220 80 a 30 50 40 0 1 90 0" stroke="black" fill="green" />
</svg>

上図は右回りに40度回転したものである。

large-arc-flag と sweep-flag

large-arc-flagは円弧が180度より大きいか小さいかを示す。大きい場合 1,小さい場合 0。 sweep-flagは円弧を正の角度(右回り)に描き始めるか負の角度(左回り)に描き始めるかを決める。 正の角度方向 1、負の角度方向 0。 全部で4通りの組み合わせがある。

large-arc-flag=0,sweep-flag=0の場合

large-arc-flag=0,sweep-flag=1の場合

large-arc-flag=1,sweep-flag=0の場合

large-arc-flag=1,sweep-flag=1の場合

円弧の角度がちょうど180度の場合、large-arc-flagは 0でも 1でも同じになる。
以下のSVG表示の方がわかりやすいかもしれない。

large-arc-flag sweep-flag 0 1 0 1

上図は [MDN Web Docs] SVG: 0から始めるSVG > パスより抜粋

上図の直線部分はすべて同じで、円弧の描き方が4通りあることを示している。 円弧の描画開始点はすべて水平方向の直線の左端になる。 円弧の描画終点はすべて垂直方向の直線の下端になる。 描画される円弧はすべて同じ半径(rx=ry=直線の長さ)の真円の一部分であり、 円の1/4または3/4に相当する部分になる。

SVGの基礎は MDN Web DocsのSVG: スケーラブルベクターグラフィック - MDN - Mozilla を参照するとよい。詳しい解説はそこにある。
本ページは、自分で実際にプログラミングした上で吟味しながら書いているが、 抜けている部分も多い。

作成日: 更新日:


back    next