SVGにおける階調度

恐らく,単なる塗り潰しや枠線より刺激的であるのは,塗り潰しや枠線と同様に階調度 (gradients)もまた作成・適用できるという事実でしょう。

階調度の種別には線状・放射状の二つがあります。当該階調度にはid属性を与えなければならず,さもなくばファイル内部の他要素が参照できません。階調度は,再利用性を高める為に,〔オブジェクトの〕形状それ自身とは対照的に,defsセクションにおいて定義します。

線状階調度

線状階調度 (linear gradients)は真っ直ぐな線に沿って〔色が〕変化します。挿入するには,<linearGradient>ノードをSVGファイルの定義セクションの内部に作成します。

基本例

<?xml version="1.0" standalone="no"?>

<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <linearGradient id="Gradient1">
        <stop class="stop1" offset="0%"/>
        <stop class="stop2" offset="50%"/>
        <stop class="stop3" offset="100%"/>
      </linearGradient>
      <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="50%" stop-color="black" stop-opacity="0"/>
        <stop offset="100%" stop-color="blue"/>
      </linearGradient>
      <style type="text/css"><![CDATA[
        #rect1 { fill: url(#Gradient1); }
        .stop1 { stop-color: red; }
        .stop2 { stop-color: black; stop-opacity: 0; }
        .stop3 { stop-color: blue; }
      ]]></style>
  </defs>
 
  <rect id="rect1" x="10" y="10" rx="15" ry="15" width="100" height="100"/>
  <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/>
  
</svg>
ScreenshotLive sample

上記は<rect>要素に線状階調度を適用する例です。線状階調度の内部には複数の<stop>ノードがあります。これらのノードは,階調度の或る位置における色を,位置についてはoffset属性,〔色については〕stop-color属性を指定することで定めます。直接又はCSSを通して割り当てられます。本例示用に,二つの手法を混合しています。具体的には,これは階調度に対して赤色から開始し,中間で透過黒色に変化し,そして青色で終了するよう指示しています。必要なだけの美醜たる混合〔色〕を作成する為に,好きなだけ停止色 (stop color)を挿入できますが,相対位置 (offset)は常に0%(又はパーセント記号を省きたいなら0)から100%(又は1)に増加するべきです。値が重複した場合,当該XML木の最遠下で割り当てられた<stop>要素が用いられます。又,塗り潰し及び枠線と同様に,その場所の透明度を設定するのにstop-opacity属性を指定できます(この場合でも,FF3においてはRGBA値をこの目的に用いることができます)。

 <stop offset="100%" stop-color="yellow" stop-opacity="0.5"/>

階調度を用いるには,対象のfill又はstroke属性からそれを参照せねばなりません。これは,urlを用いてCSS中の要素を参照する遣り方と同じことをしています。この場合,当URLは,独特な識別子である「Gradient」を与えた階調度への単なる参照です。適用するには,fillurl(#Gradient)に設定して,ジャジャーン! strokeについても同じことができます。

<linearGradient>要素はまた,階調度の大きさ及び見栄えを指定するような他の属性を幾つか持っています。x1x2y1,及びy2属性で指定された二点で階調度の方向を制御します。これらの属性は階調度が進み沿う直線を定めます。階調度は水平方向に既定されていますが,これらの属性を変えることで回転させられます。上例におけるGradient2は垂直の階調度を作成するよう設計されています。

 <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">

注意: 階調度にxlink:href属性を用いることもできます。これを用いた際は,一つの階調度からの〔<linearGradient>要素の〕属性及び色停 (stop)を別の階調度に組み入れられます。上例においては,Gradient2において全ての色停を再作成しなくてもよくなります。

 <linearGradient id="Gradient1">
   <stop id="stop1" offset="0%"/>
   <stop id="stop2" offset="50%"/>
   <stop id="stop3" offset="100%"/>
 </linearGradient>
 <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"
    xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Gradient1"/>

ここではxlink名前空間を,通常は文書の先頭にて定義するにも拘らず,当該ノード上で直接定義しました。詳細は画像について説明する際に述べます。

放射状階調度

放射状のグラデーションは直線上のグラデーションに似ていますが、ある点から放射状にグラデーションを描画します。これを作成するには <radialGradient> 要素をドキュメントの定義セクションに追加します。

<?xml version="1.0" standalone="no"?>

<svg width="120" height="240" version="1.1"
  xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="Gradient1">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
      <radialGradient id="Gradient2" cx="0.25" cy="0.25" r="0.25">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
  </defs>
 
  <rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#Gradient1)"/> 
  <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/> 
  
</svg>

ここで用いている stop は前出のものと同じですが、ここではオブジェクトの中心が赤色になり、そこから縁の青色に向けて全方向の色が変化します。直線上のグラデーションと同様に、<radialGradient> ノードも位置や方向を指定する属性を持つことができます。しかし直線上のグラデーションと異なり、これらはやや複雑です。放射状のグラデーションでも 2 つの点が定義され、それらはグラデーションの端がどこかを定義します。1 点目はグラデーションが終わる場所を囲む円を定義します。これは cx および cy 属性で定義する中心と、r 属性で定義する半径が必要です。これら 3 つの属性を設定することで、前出の例の 2 番目の長方形で表したように、グラデーションの中心の移動やサイズの変更ができます。

2 点目は焦点と呼ばれ、 fx および fy 属性で定義します。1 点目がグラデーションの端がどこかを示すのに対して、焦点はグラデーションの中心がどこかを示します。これは例を見るとわかりやすくなります。

<?xml version="1.0" standalone="no"?>

<svg width="120" height="120" version="1.1"
  xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="Gradient"
            cx="0.5" cy="0.5" r="0.5" fx="0.25" fy="0.25">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
  </defs>
 
  <rect x="10" y="10" rx="15" ry="15" width="100" height="100"
        fill="url(#Gradient)" stroke="black" stroke-width="2"/>

  <circle cx="60" cy="60" r="50" fill="transparent" stroke="white" stroke-width="2"/>
  <circle cx="35" cy="35" r="2" fill="white" stroke="white"/>
  <circle cx="60" cy="60" r="2" fill="white" stroke="white"/>
  <text x="38" y="40" fill="white" font-family="sans-serif" font-size="10pt">(fx,fy)</text>
  <text x="63" y="63" fill="white" font-family="sans-serif" font-size="10pt">(cx,cy)</text>

</svg>

焦点が先に定義した円の外側に移動した場合はグラデーションを正しく描画することができませんので、焦点は円の縁にあるものとみなされるでしょう。また焦点を定義しない場合は、円の中心と同じ場所であるとみなします。

どちらのグラデーションも、変換 (Transformations)などさまざまなことを定義する属性を持ちます。その中で、ここで説明したい属性は spreadMethod です。この属性は、グラデーションが終端に達したにもかかわらずオブジェクトがすべて塗りつぶされていない場合にどうするかを制御します。この属性は "pad"、"reflect"、または "repeat" の 3 種類の値をとることができます。"pad" はこれまで見てきたものです。グラデーションが終端に達すると最後の offset の色を、オブジェクトの残りの部分の塗りつぶしに用います。"reflect" はグラデーションを継続しますが、offset が 100% の色から始まり 0% の色へ戻るように逆向きのグラデーションを行い、その後さらに逆向きのグラデーションを行います。"repeat" もグラデーションを継続しますが、逆向きにグラデーションするのではなく最初の色から再びグラデーションを始めます。

<?xml version="1.0" standalone="no"?>

<svg width="220" height="220" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <radialGradient id="Gradient"
            cx="0.5" cy="0.5" r="0.25" fx=".25" fy=".25"
            spreadMethod="repeat">
        <stop offset="0%" stop-color="red"/>
        <stop offset="100%" stop-color="blue"/>
      </radialGradient>
  </defs>
  <rect x="50" y="50" rx="15" ry="15" width="100" height="100"
       fill="url(#Gradient)"/>
</svg>

余談ですがどちらのグラデーションも、グラデーションのサイズや方向を示すときに用いる単位系を定義する gradientUnits 属性を持ちます。この属性は userSpaceOnUse または objectBoundingBox という値を用いることができます。objectBoundingBox は既定値であり、これまで見てきたものです。この値はグラデーションをオブジェクトのサイズに調整するものであるため座標を 0 から 1 の間の値で指定する必要があり、その値は自動的に対象のオブジェクトの大きさに合わせて調整されます。userSpaceOnUse は絶対的な単位をとります。従ってオブジェクトがどこにあるかを知る必要があり、またグラデーションを同じ場所に置かなければなりません。前出の radialGradient は以下のように書き換えることができます:

 <radialGradient id="Gradient" cx="60" cy="60" r="50" fx="35" fy="35" gradientUnits="userSpaceOnUse">

gradientTransform 属性を用いてグラデーションを変換させることもできますが、まだ変換 (Transformations)の紹介 を行っていないため、後で説明します。

以上の他に、オブジェクトを包み込むボックスが長方形ではない場合に gradientUnits="objectBoundingBox" で値を扱うときの注意事項がありますが、それらはやや複雑であり、またそれの説明に詳しい方が現れるのを待たなければなりません。