svg要素の基本的な使い方まとめ

Written by defghi1977@xboxLIVE.この文書は全てテキストエディタで作成しています.えーと,そりゃもうゴリゴリと.

9.グラデーションとパターン

見栄えの良いグラフィックには色のグラデーションは欠かせない.SVGにおいても然りで,本項ではこのグラデーション処理を表すグラデーション要素について説明する.また同様に塗りつぶしに利用されるsolidColor,pattern,hatch要素についてもここで取り上げる.なおこれらの要素による塗り潰し機構をSVGではペイントサーバと呼んでいる.

グラデーションの基本構成

グラデーションは塗り潰しに用いる色を徐々に変化させることで,単色によるものに比べて滑らかな見た目をもたらす.グラフィックを描く場合には必須な機能であり,SVGにおいても帯状にグラデーションを掛けるlinearGradient要素と放射状に掛けるradialGradient要素, 及び不定形グラデーションを定めるmeshGradient要素の3つが提供されている.

SVGによるグラデーションはCSS3におけるグラデーションのように特定のプロパティに埋め込む形ではなく,別途専用の要素で定義した上で,そのグラデーションを利用する図形から参照する形を取る.グラデーションにはid属性を設定しておき,図形要素においてそのid値をfill属性,stroke属性からurl関数を用いて参照することで,グラデーションが描画される.

グラデーションは次の4つの要素から構成される.

グラデーションを施す座標系と基準の決定

グラデーションを定義する場合,まずその基準をどこに取るかが問題となる.symbol要素の所でも述べたが,通常図形要素には暗黙の内に2つの座標系が定義される.図形が描画されている座標系と図形の境界矩形(boundingBox)から発生する座標系である.前者は(transform属性が無いものとして)通常SVG要素などのviewBoxから定まるもので,後者は図形を囲む矩形を考え,その左上を原点とし,左下を(1,1)としたものである.この座標系はgradientUnits属性を使って選択することができる.

gradientUnits
グラデーションをかける座標系.
userSpaceOnUse
図形が描画される座標系
objectBoundingBox
図形が内包する座標系(規定値)

この値の切り替え方としては,図形を描画するカンバス領域を基準にグラデーションを定義したい場合はuserSpaceOnUseを,図形を基準にグラデーションを定義したい場合はobjectBoundingBoxを設定すると良い.ここで選択した座標系の上にグラデーションの方向を定める基準点をとり,グラデーションの勾配ベクトルを決定するのだが,座標系の選び方によって基準を表す属性(例えばx1,y1,x2,y2属性)の意味合いが変化する点に注意しよう.

グラデーションの色の設定

グラデーションはその勾配ベクトルを元に決定されるが,このベクトルにstop要素を使って基準となる色の位置を設定する.stop要素では色の他に不透明度を設定することが可能で,stop要素間の色は線形に補間される.なおstop要素で設定された範囲外は通常単色で塗りつぶされる.

offset
勾配ベクトルにおける色の切り替わるタイミング.0〜1の比率か,%で値を指定する.
stop-color
stop-opacity
不透明度
勾配ベクトル

stop要素はoffset値の小さい順に並べるようにしよう.これは同じoffset値のstop要素があった場合に色の境界を表すためであり,順番をバラバラにした場合にどのようなグラデーションが描かれるか判りにくくなってしまう.スクリプトなどでstop要素を操作する場合はこの特性に注意しよう.

勾配ベクトル 勾配ベクトル

グラデーションの敷き詰め設定

グラデーションはspreadMethodによってその敷き詰め方法を設定することができる.repeat及びreflectを選択した場合は勾配ベクトルを延長し,あたかもそこにstop要素が定義されているかのように動作する.

spreadMethod
敷き詰めの方法
pad
1回のみ
repeat
繰り返し
reflect
グラデーション方向を逆にして繰り返し
勾配ベクトル pad repeat reflect

グラデーションの変形

グラデーションについてはgradientTransform属性により変換することができる.グラデーションを施す際の基準となる(gradientUnitsから定まる)座標軸が予めこの属性によって変換されてから塗り潰しが行われる.設定する関数及び考え方はtransform属性と共通している.

gradientTransform
敷き詰め時の変換.transform属性と同様に,matrix,translate,rotate,scale,skewX,skewY関数をカンマ区切りで列挙する.
勾配ベクトル 勾配ベクトル

グラデーションと色の列挙

fill属性,stroke属性には指定したグラデーションが正しく参照出来なかった場合に備えて代替となる色を列挙することができる.

linearGradient:線形グラデーション

linearGradient要素は帯状に色が広がるグラデーションを定義する.

グラデーションの色の指定にはstop要素を用いる.グラデーションの勾配ベクトルはx1,y1でその始点を,x2,y2でその終点で表現する.始点から終点に向かって色を変化させる.htmlのcss3におけるlinear-gradient,repeating-linear-gradientとはグラデーション方向の指定の方法が異なる(角度の指定)ので注意が必要.

x1,y1
勾配ベクトルの始点を表す.
x2,y2
勾配ベクトルの終点を表す.
勾配ベクトル

これらの値はgradientUnitsの値により基準となる座標の基準をどこに取るかが変わる.userSpaceOnUseの例を示す.

objectBoundingBoxの例を示す.

gradientTransformを用いた例を示す.

radialGradient:放射型グラデーション

radialGradient要素により放射状(円形)のグラデーションを定義する.

使い方はほぼlinearGradient要素と同じで中心から半径の範囲にグラデーションをかける.焦点位置を指定すると放射の中心位置を変更することが出来る.gradientUnitsの指定の方法により微妙にグラデーションの生成が異なる事に注意.userSpaceOnUseの場合は常に真円のグラデーションとなる.objectBoundingBoxの場合はグラデーションの描画領域のアスペクト比に応じた楕円のグラデーションとなる.

cx,cy
グラデーションの中心位置.既定値は50%
fx,fy
焦点の位置.既定値は中心と同じ位置
r
グラデーション半径.既定値は50%

userSpaceOnUseの例.

objectBoundingBoxの例.

下はgradientTransformを掛けた例.gradientUnits=objectBoundingBoxを指定した場合,変形は描画オブジェクトのもつ座標系に対して行われる点に注意する.2つ目の例ではrotateをかけているにもかかわらずグラデーションが回転していないように見えるが,これは元々の座標系の見た目が横長であることに起因する.

焦点を定義したグラデーション

次は焦点を追加した例.若干判りにくいが,0%の色を焦点にとり,100%の色を中心から半径rの円周部分にとる.その間のグラデーションは円の中心を焦点から中心にずらしつつ半径を大きくしていき,その円周上に色を付けていく感じ.アニメーションの例を見てもらったほうが判りやすいかと思う.

焦点 中心 半径

色の境界を調整する

同一のoffset値を指定したstop要素を定義した場合,色の境界を表す.その際に境界部分におけるギザギザが気になる場合は,offset値を少しずらすと気にならなくなる.最適な値は画像の大きさやディスプレイの解像度に依存する.

meshGradient:グラデーションメッシュ

一般にオブジェクトの立体感と言ったものはlinearGradient要素, radialGradient要素のような固定されたグラデーションでは表現できない. この場合, 形状を自由に変形することが可能なグラデーションメッシュを適用すると良い. SVGではSVG2からmeshGradient要素としてグラデーションメッシュを利用できる.

注意)なお, 本記事ではinkscape0.91での動作を参考としており, 内容に間違いがあるかも知れません. また本項に記載しているコードは当面の間WEBブラウザでは正しく動作しないでしょう.

NOTE)正直な処SVGを手書きする上ではそれ程役に立たない仕組みで, 専ら他のドローツールとの連携時に効果を発揮するでしょう.

SVGにおけるグラデーションメッシュの考え方

グラデーションメッシュは他のグラデーション要素よりも複雑な構成をとる. 以下にその動作概念を示す.

  1. グラデーションを定義するためのm×nの格子を定める.
  2. 格子における縦ライン・横ラインの各交点にグラデーションの基準となる色を定義する.
  3. 格子における交点と交点とを結ぶ線分にパスを割り当てし, このパスの内容から色の補間処理を行う.
  4. この処理は格子毎に行われる. (m×n個の単位グラデーションメッシュが生成される)

meshGradient要素の構成

meshGradient要素はその仕組み上複雑な構成を採る. 以下その役割について述べる.

meshPatch要素の位置とstop要素の必要個数

meshPatch要素に記述すべきstop要素の個数は対応する格子の位置によって変化する. 一番先頭のmeshPatch要素であれば4つ必要であるが, 以降のmeshPatch要素では既に定義された格子と頂点を共有しているため3(右下の格子では2)個のstop要素で済む.

stop-color属性の省略

格子の交点にはそれぞれ横方向と縦方向の二つのグラデーションパスが定まる. この時, 既に交点に色が設定されている場合はstop-color属性の記述を省略することが出来る. (具体的には二つ目以降のmeshPatch要素の先頭のstop要素ではstop-color記述の必要がない.)

グラデーションパスの算出

stop要素のpath属性には単一のパスコマンド(L,l,H,h,V,v,Q,q,T,t,C,c,S,s,A,aの何れか)を記述する. なおパスの起点情報はmeshGradient要素のx, y属性から算出される. つまり, この座標が先頭のstop要素におけるグラデーションパスの起点として与えられると, 後続のstop要素においてはドミノ倒し式にパス起点が求まる.

path
グラデーションパスを表すパスコマンドを指定する

meshPatch要素と単位グラデーションメッシュ

meshPatch要素はstop要素で定義される4つの頂点色とグラデーションパス(辺)から構成され, この内容を元に色の補間を行う. SVGではグラデーション補間を行う為にクーンズメッシュパッチ手法を採用している. この方法では四辺に与えられたベジェ曲線によって色の変化度合いが変化する.

以下にmeshGradient要素の動作例を示す.

考察)グラデーションメッシュの欠点

グラデーションメッシュはベクタグラフィックの表現力を飛躍的に向上させるが, その代償として処理速度が犠牲となる. とりわけグラデーションメッシュはその特性から再利用が効かないため, 多用するとSVGとしての複雑度を大幅に増大させてしまう. このことから動作速度や処理負荷の軽減が重視されるWEBブラウザにおける利用は厳しく, むしろベクタ形式としての互換性を保つための仕組みと割り切るべきかもしれない. またWEBでの利用を視野に入れるのであれば, 今後buffered-rendering, color-rendering等のパフォーマンスチューニングに関わる属性とどのように組み合わせていくかが鍵となる.

色の補間処理とcolor-interpolation属性

グラデーション処理においては色を徐々に変化させて滑らかな画像を得るが,その色味の変化を計算する際に用いる色空間を指定することができる.svgではhtmlと同様に色をrgb値として扱うが,この値の取扱い方としてsRGBとlinearRGBの2つの色空間が定義されており,color-interpolation属性で選択することができる.sRGBを用いることで視覚的に自然なけっかが得られる.この属性はlinearGradient要素,radialGradient要素の他,mask要素やanimate要素に適用することができる.(filter要素には専用のcolor-interpolation-filter属性が定義されている.)

color-interpolation
画像描画・生成・合成の際の色空間を与える.ブラウザによってはグラデーションを生成する際に微妙な色味の差異が発生する(?).
auto
自動
sRGB
sRGB(規定値)
linearRGB
linearRGB

この例では上を規定値,真ん中をsRGB,下をlinearRGBに設定しているが,いずれのブラウザにおいても目立った変化は見られなかった.下の画像はadove svg viewerによる出力結果で,明確に処理結果が異なっていることが判る.sRGBを選択した方が明らかに自然なグラデーションとなっている.

solidColor:カラーパレットの定義

コンテナ要素とcolor属性を使った色設定の共通化は前に見た.しかしこの方法ではSVGの階層構造に色設定が縛られるため,利用可能な場面が限られることもある.この時SVG2で導入された単色を指定可能なsolidColor要素を持ちると,構造を意識せずに済む色の共通化を図ることが可能となる.例を示そう.

solid-color
ペイントサーバーの色を指定する
solid-opacity
ペイントサーバーの色の不透明度を指定する

但しこの方法による色の共通化はfillやstroke等のペイントサーバーを参照するものに限られる.

単色のグラーデーションでsolidColor要素を代用する

SVG2をサポートしない環境でも, 単色のグラデーションを用意することで同様の仕組みを実現できる.

pattern:パターン

pattern要素を用いるとfillやstroke属性に矩形パターンを用いた敷き詰めを指定することが出来る.linearGradient要素,radialGradient要素と同じくdefs要素にて予め定義しておく必要がある.

pattern要素においてもgradient要素と同様にパターンを描画するための座標系を選択する必要があるが,pattern要素においては,パターンそのものの座標系と,パターン内容となる図形要素が用いる座標系の2つを決定する必要があり,合計4パターンの組み合わせが存在する.以下の例では見た目が全く同じパターン敷き詰めであるが,属性値に設定している内容が異なる点に注意しよう.なおこの構造はpattern要素の他にもmask要素,filter要素においても同様である.

patternUnits
pattern要素のx,y,width,height属性をどこの座標系として使うか.
userSpaceOnUse
描画領域の座標系を使う
objectBoundingBox
描画要素の座標を比率で指定する(既定値)
patternContentUnits
パターンの内容の座標をどこに取るか.
userSpaceOnUse
描画領域の座標系を使う(既定値)
objectBoundingBox
描画要素の座標を比率で指定する

viewBox属性

pattern要素にはviewBox属性をviewBoxが指定された場合は図形の配置はviewBox属性が定める座標にて行われ,patternContentUnitsの値は無視される.

但し,patternUnitsとしてobjectBoundingBoxを指定した場合,アスペクト比の解釈がブラウザによって異なる.firefoxでは強制的にアスペクト比が変更されてしまうのだ.従ってクロスブラウザで動作させる場合はviewBox属性を使わないかpreserveAspectRatio="none"を設定してfirefoxに動作を合わせると良い.

パターンの境界の取扱い

パターンの敷き詰めはpattern要素が定める矩形パターンを基準に行われるが,その範囲外の部分は無視されてしまう.従ってパターン境界にまたがる図形を設定するには敷き詰めた後の形を意識して,図形を定義する必要がある.

パターンの変形

パターン要素においてもlinearGradient要素などと同じく図形描画の際の変換を行うことができる.

patternTransform
パターンの変換.transform属性と同様に,matrix,translate,rotate,scale,skewX,skewY関数をカンマ区切りで列挙する.

パターンの継承

pattern要素の属性値は比較的複雑であり,パターン図形のみを変えたものを複数用意する場合にこれらの値をいちいち記述するのは面倒だ.このような場合,xlink:href属性を用いることで,属性値を参照・上書きすることができる.

xlink:href
パターン設定値の参照先

パターンによるハッチング

パターンによる塗り潰しを応用することでハッチングを実現することができる.斜めのハッチングを作る場合はpatternTransform属性でパターンを回転しよう.

pattern要素利用時の注意点

図形を自動的に敷き詰めるといった機能は,簡易レイアウト機構として利用できそうであるが,次の問題から実際には上手く行かない.まずは例をよく見て欲しい.

あいうえお あいうえお

上はpattern要素を介して文字列を描画したもので,下は直接text要素を使ったものだ.よく見るとpattern要素のほうはグリフ境界が若干ボケ気味であることに気づくだろう.この動作に直接関わるsvg仕様を見つけることは出来なかったが,pattern要素の図形はかなり早い段階でラスタライズされているものと推察される.塗り潰し処理のためにpattern要素内部の図形は先行してラスタライズされ,その後svg要素全体がラスタライズされるのだ.(この動作はsvg実装の都合上仕方のないことだ)

スクリーン上ではそれほど気にならないものの,印刷処理においてこの動作は致命的な品質低下をもたらす.pdf形式で出力するとよく判るが,pattern要素に相当する部分が先行してラスタライズされ,ラスタ形式の画像となってしまうのだ.

従ってpattern要素は図形の装飾が基本的な目的で定義されており,見た目を重視するようなレイアウト用途で利用するのは推奨されないことに注意しよう.

hatch/hatchPath:ハッチング

pattern要素によるハッチングは記述が煩雑になりすぎることから, SVG2ではハッチング専用の仕組みが導入される.

under construction.

ペイントサーバの重ねあわせ

SVG2においてはfill属性, stroke属性共に複数のペイントサーバを列挙することで塗りを重ねることが可能となる.

この記述はSVG1.1では許されていないが, use要素を使って再現することが出来る.