SVGにおいてはグラフィック描画の手続きをXMLツリーとして表現する.様々な要素の組み合わせで複雑なグラフィックを構成するのだ.本項では最も基本のpath要素とその他の基本図形要素,及びg要素による図形のグループ化について説明する.これらの要素はSVGを表示可能な全ての環境で動作し,簡単なグラフィックであればこれだけで十分に間に合う.
SVGにおいてはグラフィック描画の手続きをXMLツリーとして表現する.様々な要素の組み合わせで複雑なグラフィックを構成するのだ.本項では最も基本のpath要素とその他の基本図形要素,及びg要素による図形のグループ化について説明する.これらの要素はSVGを表示可能な全ての環境で動作し,簡単なグラフィックであればこれだけで十分に間に合う.
path要素は任意の図形を表す.図形定義が柔軟に行えるが,円や四角などの単純な図形を描画するだけなら後述する専用の要素を使ったほうが良い.
d属性には曲線を引く際のコマンド(パスコマンド)のリスト(パスデータ文字列)を指定する.パスデータ文字列の前から順にコマンドを実行し,得られた(曲)線に囲まれた領域をパス図形と呼ぶ.SVGにおけるグラフィックはこのパス図形を元に描画される.
d属性に設定できるコマンドを示す.コマンドの後ろには座標やフラグ値をカンマ/スペース区切りで記述する.このコマンド群は後述するanimateMotion要素でも用いられる.
なお,SVGにおけるパス図形の定義はSVGのみならず,様々な環境で利用できる.そのため,ツールによるSVG出力結果を他のアプリケーション環境で再利用することが可能だ.
Mコマンドにより曲線の始点を指定し,その他のコマンドを用いて次の頂点を指定していく.Zコマンドを実行した場合はMコマンドで指定した座標に自動的に直線が引かれ図形が閉じられる.なおZコマンドは指定しなくても良く,その場合は単なる折れ線(開いた図形)として扱われる.
Mコマンドを途中で指定すると現在位置をスキップすることが出来る.Zコマンドを指定した後でMコマンドを開始することも出来る.これは複数の図形を1つのパスとして表したい場合に利用する.(逆に「M」でd操作文字列を分解すれば,複数のpath要素に分割すると言ったことも可能だ)
各コマンドには絶対位置指定(大文字)と相対位置指定(小文字)の2種類が提供されている.相対位置指定を選択すると,直前に指定した頂点の座標を基準とした相対位置で次の頂点を指定することが出来る.相対位置指定でコマンドを定義しておくと,パスの起点を変更するだけでパス全体を移動させることができる.一方絶対位置指定では単一の座標を変更してもその他のパスの構成点は変化しないため,パスをアンカー的な扱いをする場合はこちらのほうが有利だ.
同じコマンドを連続して用いる場合はコマンドの記述を省くことが出来る.が,見通しが悪くなるので多用は禁物である.
Mコマンドの後ろに座標を連ねた場合はLコマンドとして扱われる.
線の色はstroke,線の幅はstroke-width,塗りつぶしの色はfillで設定する.strokeとfillの両方に値が設定された場合は,塗り潰しの上に線が描画される†.以降の基本図形においても同様である.なお,strokeで描画される線はhtmlにおけるborderとは動作が異なる点に注意する.htmlのborder属性では要素を囲むように境界が描画されるが,svgのstroke属性による線の描画は線の中央が丁度図形の境界となる.
†なおSVG2をサポートしている環境であればpaint-orderプロパティによりこの順番を変更することができる.
svgでは様々な場面でグラフィックの色を指定することとなるが,svgで利用可能な色の指定方法としては次のものがある.
この内,rgba関数,hsl関数,hsla関数による色の指定はsvg1.1では定義されていないもの,css3の機能として先行実装されたもので,svg2から正式にサポートされることとなっている.
図形に色を付けたくない,塗り潰したくない場合は「none」を指定するか,透明を表す「rgba(0,0,0,0)」(黒の透明)を指定するようにする.transparent(htmlにおける透明を表すキーワード)はoperaで対応しておらず黒で表示されてしまう.勘違いしやすいが「none」は透明を表すキーワードではなく,そこに塗り潰し領域が存在しない事を表す.その結果,後述するマウスイベント等が図形上で発生しなくなり,a要素におけるリンクも無効となると言った効果もある.これらの処理が必要な場合はpointer-eventsをall等に設定すると良い(詳しくは後述).下記に例を示す.緑色の枠にカーソルを当ててもイベントが発生していないことが判る.
path要素では直線を引くコマンドとしてLコマンド,Hコマンド,Vコマンドの3つ(絶対位置,相対位置を分けると6つ)が提供されている.Lコマンドは現在位置から任意の座標に,Hコマンドは現在の位置から水平方向(x軸方向)に,Vコマンドは垂直方向(y軸方向)に線を引く場合に用いる.上手く使い分けることでコマンドの記述量を減らすことができる.
svgでは曲線を引くためにベジェ曲線コマンドが提供されている.
2次ベジェ曲線を引くにはQコマンド及びTコマンドを用いる.Qコマンドでは制御点と次頂点の2つを指定する.
Tコマンドを用いて制御点の指定を省略することが出来る.前回用いた制御点から点対称の位置を新たな制御点として利用することで,曲線を滑らかにつなぐ.
3次ベジェ曲線を引くにはCコマンド及びSコマンドを用いる.Cコマンドでは始点に対する制御点,終点に対する制御点,次頂点(終点)の合わせて3つの点を指定する.制御点から頂点に引いた直線に接するように曲線が引かれる.
Sコマンドを用いて始点に対する制御点を省略することが出来る.前回用いた制御点から点対称の位置を新たな制御点として利用することで,曲線を滑らかにつなぐ.
先のベジェ曲線はどちらかというとグラフィックツール向けの機能だが,次に示す円弧の引き方はテキストベースでのsvg記述においても便利な機能だ. 円弧を引くにはA操作を行う.一般に始点と終点を通る半径が一定の円弧を考えると,長くて時計回り短くて時計回り長くて反時計回り短くて反時計回りの4曲線が得られる.従って,始点から終点に円弧を書く際にどのような円弧を引くかについてlarge-arc-flagでは円弧の長さの選択し,sweep-flagでは円弧の方向を選択する.
角度は右へ伸びる線分を0度としそこから時計回りに数える.
構文は「A rx,ry x-axis-rotation large-arc-flag,sweep-flag x,y」と非常に長いので面倒ではある.
半径の設定が始点と終点との距離よりも短い場合,円弧は自動的に拡大される.その際,楕円の中心は始点と終点の中央に合わせられ,sweep-flagは無視される.
なお,何らかの目的があってpath要素で閉じた円を描画したい場合(例えばtextPath要素でテキストを円周上に並べたい場合など)は,一旦2つの半円に分け,それらを繋げるようにする.というのも,始点と終点が同じ場合円弧を引くことができないからだ.
このような仕様になっているのは,円弧を他の曲線・直線と連結できるようにしているためで,中心と半径と角度を与えて円弧を描きたい場合には(三角関数を使って)端点の座標を算出する必要があるために非常に面倒である.このとき扇形を作りたいだけなら,circle要素で描いた円を別の図形で隠す方法もある.transform属性を使って覆いとなる図形を回転させることで扇形に見せるのだ.
複数のpath要素のd属性を連結することでパスの統合を行うことが出来る.またMコマンドで分割することで複数のパスに分離することができる.なお,mコマンドが指定されていた場合はパスの開始位置が直前のパスの終了位置からの相対指定となるため,位置がずれる点に注意しよう.
3次ベジェ曲線はその汎用性から広範な環境で利用されており,様々な特徴が数学的に確かめられている.svgにおいてもこれらの特徴をそのまま利用することができるので,いろいろ調べてみると良い.
一般にpath要素で記述する図形はA操作による円弧を除き全て3次ベジェ曲線に変換することができる.実際,任意の2次のベジェ曲線は3次ベジェ曲線に変換することができる.新たな制御点はもともとの制御点に対して丁度2/3の位置に取るようにする.参照元
この変換は後に説明するアニメーションにおいて重宝する.d操作の形を揃えることでパス間の変形を自由に行えるようになるのだ.
A操作による円弧も実用上問題がない程度に3次ベジェ曲線で近似することができる.半径に対し制御点を0.5522847倍の位置に定める.(実際ブラウザ内部でもこのように処理されているのかもしれない.)
このケースは中心角90°の円弧をベジェ曲線で近似したが,任意角度の円弧を近似することもできる.方法については参照元に詳しい.
ベジェ曲線を用いると,一般的に作図が面倒な放物線や3次曲線等を記述することができる.参照元.一般にどの放物線も平行移動・拡大・縮小・反転させることで重ね合わせることができるため,基本形を憶えておくと,d属性内部の座標を伸縮するだけで自由に放物線を記述できるようになる.但しtransform属性による変形は線の太さが変化するためお勧めできない.
尖った放物線を描く際,端点が描画範囲を大きく外れる場合は,clip-path属性で描画範囲を制限するとよい.
放物線の例をもうひとつ示す.点(0,0)から(1,1)へ放物線を引く場合,3次ベジェ曲線の制御点を(1/3,0),(2/3,1/3)に取ることで丁度放物線となる.これはアニメーションを定義する際,スプライン関数を使って自由落下のような動きを実現するのに非常に便利である.構造も判りやすいので,暗記してしまおう.
通常path要素のd属性の座標指定には単位を指定することが出来ない.その為本来%指定によるpath図形の描画は出来ないのだが,svg要素を入れ子として次のようにviewBox属性を0 0 100 100及びpreserveAspectRatioをnoneとすると,内部での幅と高さが100となり%で指定した場合と同じこととなる.
なおこの方法を利用した場合,stroke属性による線の描画幅に影響を及ぼす点に注意する.この問題はsvg1.2tinyのvector-effect属性を使うことで回避できる.
他の単位については下記のように単位領域に1×1のviewBoxを指定することで同様の記述ができる.overflow属性にvisibleを指定するとsvg要素の範囲外への図形描画が有効となることを利用する.
直線,円,楕円,四角形,折れ線,多角形は全てpath要素で記述できるが,これらの基本的な図形については専用の要素が用意されている.path要素のd属性の可読性は余りよくないので,普段はこれらの要素を用いることとなるだろう.
line要素は直線を表す.属性値に始点と終点とを指定することで直線を引くことができる.終点を始点からの相対位置で指定したい場合はpath要素を用いると良い.
rect要素は四角形を表す.左上の座標と幅,高さを指定することで四角形を作成することができる.また,頂点の半径を与えることで角が丸まる.なお,htmlでのborder-radiusのような角毎に半径を指定することはできないようだ.このようなケースでは面倒だがpath要素を使うしか無い.
半径の値を辺の長さの半分(よりも大)に取るとrect要素で円や楕円を描画することができる.左上を描画の基準とするため,中心を描画の基準とするcircle要素,ellipse要素と使い分けると良い.
circle要素は円を表す.中心の座標と半径を指定することで円を作成することが出来る.
ellipse要素は楕円を表す.中心の座標と横方向の半径rxと縦方向ryの半径とを指定することで楕円を作成することが出来る.
polyline要素は折れ線を表す.points属性に頂点のリストを設定することで折れ線を作成することが出来る.
polygon要素は多角形を表す.polyline要素との違いはpathが閉じられるか否かである.
path・polyline・polygon要素を用いて塗りつぶし・敷き詰めを行った場合,その方法をfill-ruleで指定することができる.evenoddを指定すると線によって囲まれた領域が何本の線分に囲まれているかによって塗る・塗らない(白抜き)が切り替わる.この白抜きは憶えておくと便利かもしれない.
path要素においてはfill-ruleがnonzeroであっても,白抜きとなるケースが発生する.複数のパスから構成されたpash図形であった場合,互いにパスの向きが逆向きであった場合は,内側と外側とが打ち消し合い,fill対象の領域から除外される.
strokeで引かれる線について様々な装飾を行うことができる.
stroke-dasharrayを設定すると点線になる.描画部と非描画部の長さをリスト形式で記述し,点線のパターンを定義する.stroke-dashoffset属性は点線の開始位置を指定する.
図形が複数のパーツから構成されていた(つまりpath図形にmコマンドによるジャンプが存在する)場合,そのパーツ毎に点線の描画処理が行われる.
stroke-linecapで端点のスタイル,stroke-linejoinで頂点のスタイルを指定する.stroke-widthの値を大きく取ると端点,頂点の形が目立つようになるが,これらのスタイルを設定することでより見栄えのする線を引くことが可能となる.この値はcanvas要素における内容と同じである.
miter長は頂点からstrokeによる頂点までの距離であり,miter長/(stroke幅/2)(この値は頂点が為す角度から自動計算される)がstroke-miterlimit値よりも大きくなると自動的に面取り処理がなされる.従って十分に大きな値を設定しておけば面倒な計算を行うこと無く角を尖らせることが出来る.
stroke-dasharray属性とstroke-linecap属性を使って丸い点線を描くことができる.stroke-widthとstroke-dasharrayの値を調整し,丸の間隔を制御する.なお,長さ0の取扱いがブラウザによって異なるため,不都合がある場合は0の値を0.1とするなど目立たない程度に値を取ると良い.
stroke-dasharray属性及びstroke-dashoffset属性は一般に点線を定義するためのものと思い込みがちだが,値を十分に大きく取ることでpath図形の一部にstrokeを引くといった用途に応用することが出来る.この場合,パスの道のりを基準とした描画となる.
その際にpathLength属性を使ってpath要素で描画されるラインの形式的な長さを指定することで設定する値を簡略化することが出来る.なおブラウザによってpathLengthの影響を受ける属性の種類が異なる.
rect要素・circle要素・ellipse要素で定義される図形に対しstroke-dasharrayを使った点線の描画を行う場合,その図形の描画起点を考える必要がある.
rect要素については図形の左上を起点とし,時計回りにパスを描く.但し角が丸まっていた場合はその分右に起点をずらすこととなる.
circle要素・ellipse要素については概ね中心から見て0°の方向から時計回りにパスを描く.
グラフなどを描画する際,図形の境界をくっきり表示させたい場合がある.このような場合は,属性shape-renderingにcrispEdgesを指定することでアンチエイリアシング処理を省き,境界を明確化することが出来る.なお,形状によっては非常に見苦しい結果となるので,適用する図形を吟味した上で利用したい.
g要素は図形をグループ化する.複数の図形を論理的にグループ化しグラフィック構造を明確化し,スタイルの設定を容易にする.なお図形固有の配置(位置とサイズ)についてはまとめることができない(詳しくはstyle要素の項で述べる).g要素は階層構造をとることができる.ここでは2つの円にtransform属性を一括設定してみた.
要素に直接プレゼンテーション属性が設定されていた場合は,そちらの設定値が優先される.未設定の場合は一番近くのg要素の設定値が用いられる.
なお例外もあって,g要素に設定された際にグループ化した図形全体に対する設定を与えるものもある.opacity, stroke-opacity, fill-opacity, mask, filterがこれに相当する.従って図形要素とg要素の両方にスタイルが指定されていた場合に思わぬ結果を引き起こす場合がある.
概念上のg要素の用い方はこれで良いが,内部的な動作を捉えておこう.g要素が宣言されると,その中の図形は一時的な描画領域に描きこまれ,全ての図形の描画が完了した後に一時的な描画領域の内容が元の描画領域に複写されるのだ.描画のサブルーチン化とも言えるかもしれない.※ドローイングツールにおけるレイヤである.従って,g要素は図形をまとめると言った用途だけでなく,filterやmask等の画像処理の順番を制御する目的にも用いられる点を憶えておこう.
なおSVG2ではこの定義が変更され,よりグラフィックの構造化を主眼としたものとなった.
ここまでで塗りつぶしの色にはfill属性を,線の色にはstroke属性を用いることを学んだ.ただこのままだと異なる属性に同一の色を指定するのがいささか面倒である.このような場合はg要素とcolor属性を用いることで色設定の共通化を図ることができる.
使い方の例を示す.次の例は最も素朴な例だ.2つのrect要素のfill属性,stroke属性に同じ色を設定している.
これをg要素を用いて書き換えたもの.色を扱う要素においてはfill属性やstroke属性に「currentColor」を設定することでcolor属性に設定された色を参照するようになる.この特徴を踏まえて,g要素のcolor属性に色を指定することで,rect要素のfill属性,stroke属性の両方に同じ色がされている.全く同じ描画結果ながら色の設定が1箇所にまとまり大分見通しが良くなったはずだ.
colorの値をcssで指定しても同じ結果となる.
もうひとつの特徴として,svg要素を含んでいるhtml要素(例えばdiv要素)についてcssのcolorプロパティが設定されていると,svg要素内部の図形にそのcolor属性が引き継がれる.この特徴を利用してHtmlの文字列とsvg要素の色とを一括して定義するといった利用も可能である.この機能は非常に役に立つので絶対に憶えておいたほうが良い.
色 | 色名 | r,g,b値 |
aliceblue | 240, 248, 255 | |
antiquewhite | 250, 235, 215 | |
aqua | 0, 255, 255 | |
aquamarine | 127, 255, 212 | |
azure | 240, 255, 255 | |
beige | 245, 245, 220 | |
bisque | 255, 228, 196 | |
black | 0, 0, 0 | |
blanchedalmond | 255, 235, 205 | |
blue | 0, 0, 255 | |
blueviolet | 138, 43, 226 | |
brown | 165, 42, 42 | |
burlywood | 222, 184, 135 | |
cadetblue | 95, 158, 160 | |
chartreuse | 127, 255, 0 | |
chocolate | 210, 105, 30 | |
coral | 255, 127, 80 | |
cornflowerblue | 100, 149, 237 | |
cornsilk | 255, 248, 220 | |
crimson | 220, 20, 60 | |
cyan | 0, 255, 255 | |
darkblue | 0, 0, 139 | |
darkcyan | 0, 139, 139 | |
darkgoldenrod | 184, 134, 11 | |
darkgray | 169, 169, 169 | |
darkgreen | 0, 100, 0 | |
darkgrey | 169, 169, 169 | |
darkkhaki | 189, 183, 107 | |
darkmagenta | 139, 0, 139 | |
darkolivegreen | 85, 107, 47 | |
darkorange | 255, 140, 0 | |
darkorchid | 153, 50, 204 | |
darkred | 139, 0, 0 | |
darksalmon | 233, 150, 122 | |
darkseagreen | 143, 188, 143 | |
darkslateblue | 72, 61, 139 | |
darkslategray | 47, 79, 79 | |
darkslategrey | 47, 79, 79 | |
darkturquoise | 0, 206, 209 | |
darkviolet | 148, 0, 211 | |
deeppink | 255, 20, 147 | |
deepskyblue | 0, 191, 255 | |
dimgray | 105, 105, 105 | |
dimgrey | 105, 105, 105 | |
dodgerblue | 30, 144, 255 | |
firebrick | 178, 34, 34 | |
floralwhite | 255, 250, 240 | |
forestgreen | 34, 139, 34 | |
fuchsia | 255, 0, 255 | |
gainsboro | 220, 220, 220 | |
ghostwhite | 248, 248, 255 | |
gold | 255, 215, 0 | |
goldenrod | 218, 165, 32 | |
gray | 128, 128, 128 | |
grey | 128, 128, 128 | |
green | 0, 128, 0 | |
greenyellow | 173, 255, 47 | |
honeydew | 240, 255, 240 | |
hotpink | 255, 105, 180 | |
indianred | 205, 92, 92 | |
indigo | 75, 0, 130 | |
ivory | 255, 255, 240 | |
khaki | 240, 230, 140 | |
lavender | 230, 230, 250 | |
lavenderblush | 255, 240, 245 | |
lawngreen | 124, 252, 0 | |
lemonchiffon | 255, 250, 205 | |
lightblue | 173, 216, 230 | |
lightcoral | 240, 128, 128 | |
lightcyan | 224, 255, 255 | |
lightgoldenrodyellow | 250, 250, 210 | |
lightgray | 211, 211, 211 | |
lightgreen | 144, 238, 144 | |
lightgrey | 211, 211, 211 | |
lightpink | 255, 182, 193 | |
lightsalmon | 255, 160, 122 | |
lightseagreen | 32, 178, 170 | |
lightskyblue | 135, 206, 250 | |
lightslategray | 119, 136, 153 | |
lightslategrey | 119, 136, 153 | |
lightsteelblue | 176, 196, 222 | |
lightyellow | 255, 255, 224 | |
lime | 0, 255, 0 | |
limegreen | 50, 205, 50 | |
linen | 250, 240, 230 | |
magenta | 255, 0, 255 | |
maroon | 128, 0, 0 | |
mediumaquamarine | 102, 205, 170 | |
mediumblue | 0, 0, 205 | |
mediumorchid | 186, 85, 211 | |
mediumpurple | 147, 112, 219 | |
mediumseagreen | 60, 179, 113 | |
mediumslateblue | 123, 104, 238 | |
mediumspringgreen | 0, 250, 154 | |
mediumturquoise | 72, 209, 204 | |
mediumvioletred | 199, 21, 133 | |
midnightblue | 25, 25, 112 | |
mintcream | 245, 255, 250 | |
mistyrose | 255, 228, 225 | |
moccasin | 255, 228, 181 | |
navajowhite | 255, 222, 173 | |
navy | 0, 0, 128 | |
oldlace | 253, 245, 230 | |
olive | 128, 128, 0 | |
olivedrab | 107, 142, 35 | |
orange | 255, 165, 0 | |
orangered | 255, 69, 0 | |
orchid | 218, 112, 214 | |
palegoldenrod | 238, 232, 170 | |
palegreen | 152, 251, 152 | |
paleturquoise | 175, 238, 238 | |
palevioletred | 219, 112, 147 | |
papayawhip | 255, 239, 213 | |
peachpuff | 255, 218, 185 | |
peru | 205, 133, 63 | |
pink | 255, 192, 203 | |
plum | 221, 160, 221 | |
powderblue | 176, 224, 230 | |
purple | 128, 0, 128 | |
red | 255, 0, 0 | |
rosybrown | 188, 143, 143 | |
royalblue | 65, 105, 225 | |
saddlebrown | 139, 69, 19 | |
salmon | 250, 128, 114 | |
sandybrown | 244, 164, 96 | |
seagreen | 46, 139, 87 | |
seashell | 255, 245, 238 | |
sienna | 160, 82, 45 | |
silver | 192, 192, 192 | |
skyblue | 135, 206, 235 | |
slateblue | 106, 90, 205 | |
slategray | 112, 128, 144 | |
slategrey | 112, 128, 144 | |
snow | 255, 250, 250 | |
springgreen | 0, 255, 127 | |
steelblue | 70, 130, 180 | |
tan | 210, 180, 140 | |
teal | 0, 128, 128 | |
thistle | 216, 191, 216 | |
tomato | 255, 99, 71 | |
turquoise | 64, 224, 208 | |
violet | 238, 130, 238 | |
wheat | 245, 222, 179 | |
white | 255, 255, 255 | |
whitesmoke | 245, 245, 245 | |
yellow | 255, 255, 0 | |
yellowgreen | 154, 205, 50 |