単純な塗りつぶしや枠線より面白いであろう効果として、fill や stroke にグラデーションを作成および適用できます。
グラデーションは直線状と放射状の 2 種類を使用できます。直線状のグラデーションは直線に沿って色が変わります。グラデーションを入れるには、SVG ファイルの定義セクション内に <linearGradient>
ノードを置きます。グラデーションは id
属性で与えなければなりません。さもなければファイル内の他の要素から参照されず、基本的には役に立たないものになります。
<?xml version="1.0" standalone="no"?> <svg width="120" height="240" version="1.1" xmlns="https://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>
上記は <rect>
要素に直線状のグラデーションを適用する例です。直線状のグラデーション内には複数の <stop>
ノードがあります。これらのノードはグラデーションでどの位置にどの色を置くかについて、offset
属性で位置、stop-color
属性で色を指定します。これは直接あるいは CSS を通して割り当てます。ここでは例として、2 種類の使い方を混在させました。例えば、上記の例はグラデーションを始めは赤色、中間で透過した黒色に変わり、最後は青色にしています。必要な美しさに応じた色の混ぜ合わせのために多くの stop 色を入れることができますが、offset は必ず 0% (パーセント記号を使わない場合は 0) から 100% (または 1) に増えていかなければなりません。値が重複するときは、XML ツリーでもっとも後に割り当てられた stop を用います。fill や stroke と同様に、特定の場所の不透明度を示す stop-opacity
属性を指定できます (繰り返しになりますが、FF3 では RGBA 値を用いることもできます)。
<stop offset="100%" stop-color="yellow" stop-opacity="0.5"/>
グラデーションを用いるには、オブジェクトの fill または stroke 属性からそれを参照しなければなりません。これは CSS で要素を参照するのと同じ方法である、url
を用いて行われます。この場合 URL はグラデーションを参照するだけであり、それには独特な ID "Gradient" を与えたとします。そのとき、グラデーションを適用するには fill に url(#Gradient)
を設定します。すると、オブジェクトが複数の色で塗られます。同じことを stroke でも行えます。
<linearGradient>
要素はこれまで見た属性の他に、グラデーションのサイズや見栄えを指定する属性も持ちます。グラデーションの方向は x1
、x2
、y1
、および y2
属性で示される 2 つの "点" で操作します。これらの属性は、グラデーションの流れが沿う直線を定義します。グラデーションはデフォルトで水平方向に流れますが、これらの属性を変えることで向きを回転させることができます。前出の例の Gradient2 は、垂直方向のグラデーションを作成するよう設計しました。
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
xlink:href
属性を用いることもできます。これを使うと、あるグラデーションの属性や stop を別のグラデーションにインクルードさせることができます。前出の例では、Gradient2 で全ての stop を再作成する必要がなくなります。 <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="https://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="https://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="https://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="https://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"
で値を扱うときの注意事項がありますが、それらはやや複雑であり、またそれの説明に詳しい方が現れるのを待たなければなりません。