HTML SVG の基本的な使い方(SVG入門)
SVG の基本的な使い方に関する覚書です。
HTML ファイルに直接 svg 要素を記述するインライン SVG の使い方(viewBox の説明や動作確認サンプル、基本図形要素、fill と stroke、スタイルの設定、グループ化を行う g 要素や再利用可能な部品の定義に使う defs 要素、図形などのひな形を定義するための symbol 要素、マーカー、変形、グラデーション、パターン、クリッピングやマスキング)や SVG ファイルの最適化などの基本的な事項をまとめています。
以下は2020年12月時点での内容になります。仕様などに関しては変更になる可能性があります。
関連ページ:
- SVG アニメーション(SMIL を使ったアニメーション)
- CSS clip-path の使い方
- CSS マスキング mask-image の使い方
- Photoshop で SVG
- CSS Shapes / shape-outside
- JavaScript でアニメーション Web Animation API
更新日:2023年07月30日
作成日:2020年12月24日
SVG とは
SVG は Scalable Vector Graphics の略で、二次元グラフィックスを XML で記述するための言語(テキストファイル)であり、ベクター形式の画像フォーマットでもあります。
SVG の仕様などについては以下のサイトで確認することができます。
- Scalable Vector Graphics (SVG) 1.1 (Second Edition)
- SVG 1.1 仕様 (第2版) 日本語訳
- Scalable Vector Graphics (SVG) 2
- Scalable Vector Graphics (SVG) 2 日本語訳
- MDN Web Docs: SVG 要素リファレンス
- MDN Web Docs: SVG 属性リファレンス
- MDN Web Docs: SVG教本
SVG の使い方の詳細については以下のサイトがとても参考になります。
現在は代表的な最新ブラウザー全てで SVG が利用可能です(caniuse svg)。但し、指定する属性によってはサポートされている状況に違いがあるようです。
また、一部のブラウザーではファビコンも SVG 形式に対応しています(caniuse svg favicon)。
SVG を Web で利用する(SVG 形式のファイルを HTML で表示する)には以下のような方法があります。
- 画像ファイルとして読み込んで表示(img タグや CSS、ファビコンなど)
- object タグを使って表示
- svg 要素として記述(コードをインラインで記述して表示)
※ 但し、img タグや CSS で表示する場合、表示された SVG 画像に対して画像のパーツごとにスタイルを指定したり、JavaScript 等で操作することができません。
画像ファイルとして読み込んで表示
SVG は画像ファイル(外部ファイル)として img 要素の src 属性で指定したり、CSS の background-image などを使って読み込むことができます。
SVG ファイルの拡張子は .svg です(gzip 圧縮された場合は .svgz になります)。
<img src="../images/sample-01.svg" width="50" height="50" alt="">
CSS の background-image で背景画像として指定
<div class="bg-svg"></div>
.bg-svg { width: 50px; height: 50px; background-image: url("../images/sample-01.svg"); }
以下はファビコンの設置例です。type 属性(MIME タイプ)を image/svg+xml にします。また、対応していないブラウザ用に PNG 形式のファビコンも設置しています。(参考:css-tricks)
<link rel="icon" href="images/favicon.svg" type="image/svg+xml"> <link rel="icon alternate" href="images/favicon.png" type="image/png">
object タグを使って表示
object タグを使って表示するには、type 属性(MIME タイプ)に image/svg+xml、data 属性に表示する SVG ファイルの URL を指定します。
<object type="image/svg+xml" data="../images/sample-01.svg" width="50" height="50"></object>
svg 要素として記述(インライン SVG)
HTML5 では svg 要素を HTML の中に直接記述(コードをインラインで記述)することができます。
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 200 200"> <style type="text/css"> .st0{fill:#7AC385;stroke:#356837;} </style> <circle class="st0" cx="100" cy="100" r="100"/> </svg>
上記のように記述した SVG は、HTML の DOM の一部になります(DOM ツリーとしてブラウザ内部に保持され、CSS や javascript 等で操作することができます)。
以下は Bootstrap Icons の SVG アイコンを表示する例です。この例では svg 要素の width と height を 32px に指定していますが、CSS でスタイルを設定することもできます。
また、CSS の transition でホバー時に回転と拡大及び色を変更するアニメーションを設定しています。
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-music-note-beamed" viewBox="0 0 16 16"> <path d="M6 13c0 1.105-1.12 2-2.5 2S1 14.105 1 13c0-1.104 1.12-2 2.5-2s2.5.896 2.5 2zm9-2c0 1.105-1.12 2-2.5 2s-2.5-.895-2.5-2 1.12-2 2.5-2 2.5.895 2.5 2z"/> <path fill-rule="evenodd" d="M14 11V2h1v9h-1zM6 3v10H5V3h1z"/> <path d="M5 2.905a1 1 0 0 1 .9-.995l8-.8a1 1 0 0 1 1.1.995V3L5 4V2.905z"/> </svg>
.bi-music-note-beamed { transition: 0.6s; margin: 30px 0; } .bi-music-note-beamed:hover { transform: rotate(360deg) scale(1.3); color: lightskyblue; }
関連項目: symbol 要素 アイコンを表示
SVG の最適化
単純な画像は SVG の基本図形要素で記述できますが、複雑な画像は Illustrator などで作成した画像を SVG に変換(保存)して使用したりします(以下では単純な円の画像を例として使用しています)。
Illustrator や各種ツールで生成した SVG には Web で使用する場合には不要なデータが含まれています。
例えば Illustrator の場合、Web 向けに最適化された SVG 書き出しオプションを使えば不要なデータは少いですが、別名保存で SVG ファイルとして保存すると不要なデータがかなり含まれています。
以下は Illustrator で 240x240 ピクセルのアートボードに描画した画像を別名保存で SVG ファイルとして保存する例です。
ファイル形式を SVG にします。
「Illustrator の編集機能を保持」のチェックを外します。
「SVG コード」をクリックすると SVG のコードを確認することができ、表示されたコードを利用することができます。以下が生成されたコードの例ですが、Web で使用するには不要なコメントや属性が記述されています。
<?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 400 400" style="enable-background:new 0 0 400 400;" xml:space="preserve"> <style type="text/css"> .st0{fill:#6EC8E5;stroke:#3876BC;stroke-miterlimit:10;} </style> <circle class="st0" cx="200" cy="200" r="120"/> </svg>
以下は書き出し形式を指定して SVG として書き出す例です。
ファイル形式を SVG にします。
以下のようなダイアローグボックスが表示されるので「コードを表示」をクリックするとコードを確認することができ、表示されたコードを利用することができます。
以下は「縮小」と「レスポンシブ」のチェックを外した場合のコードの例です。
別名保存でのコードに比べると不要なコードが減っているのが確認できます。また、「レスポンシブ」のチェックを入れていないので width="241" height="241"(Illustrator のアートボードでの設定は 240px)で svg 要素に幅と高さが設定されています。
<svg id="レイヤー_1" data-name="レイヤー 1" xmlns="http://www.w3.org/2000/svg" width="241" height="241" viewBox="0 0 241 241"> <circle cx="120.5" cy="120.5" r="120" style="fill: #6ec8e5;stroke: #3876bc;stroke-miterlimit: 10"/> </svg>
「レスポンシブ」にチェックを入れると、幅と高さの属性が削除され以下のようなコードになります。「縮小」にチェックを入れるとミニファイされます。
<svg id="レイヤー_1" data-name="レイヤー 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 241 241"> <circle cx="120.5" cy="120.5" r="120" style="fill: #6ec8e5;stroke: #3876bc;stroke-miterlimit: 10"/> </svg>
実際に上記のコードを使う場合は data-name="レイヤー 1" は不要ですし、id の値は「レイヤー_1」では使えないので書き換えるか削除します。また、HTML5 でインライン SVG として記述する場合は xmlns 属性も省略できるので以下のように記述することができます。
<div style="max-width: 100px"> <svg viewBox="0 0 241 241"><!-- この場合、親要素に幅を指定 --> <circle cx="120.5" cy="120.5" r="120" style="fill: #6ec8e5;stroke: #3876bc;stroke-miterlimit: 10"/> </svg> </div>
Illustrator の SVG 関連リンク
関連ページ
最適化ツール SVGO
SVG ファイルを最適化(不要なデータを取り除いて軽量化)するツールとしては SVGO(SVG Optimizer)が有名です。
SVGO は Node.js ベースのツールなので、Node.js がインストールされていれば簡単に導入できます。
$ npm install -g svgo return // svgo をグローバルインストール
以下は sample.svg を最適化して sample.min.svg という名前で保存する例です。-o は出力先(output)を指定するオプションです。
出力先(ファイルやフォルダ名)を指定しないと上書きされてしまうので注意が必要です(後で編集が必要な場合に大変です)。
$ svgo sample.svg -o sample.min.svg return Done in 17 ms! 0.489 KiB - 68.5% = 0.154 KiB //68.5% 縮小
<?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 400 400" style="enable-background:new 0 0 400 400;" xml:space="preserve"> <style type="text/css"> .st0{fill:#6EC8E5;stroke:#3876BC;stroke-miterlimit:10;} </style> <circle class="st0" cx="200" cy="200" r="120"/> </svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400"><circle cx="200" cy="200" r="120" fill="#6ec8e5" stroke="#3876bc" stroke-miterlimit="10"/></svg>
-f オプションを指定してフォルダごと最適化することができます。
svgo -f フォルダへのパス -o 出力先フォルダへのパス
以下はカレントディレクトリのファイル全てを最適化してカレントディレクトリの中に min フォルダを作成して保存する例です。
$ svgo -f ./ -o ./min/
どのような最適化が行われるかは What it can do に記載されています。多くの最適化のオプション(プラグイン)がデフォルトで有効になっています。
convertShapeToPath は基本図形要素をパスに変換するオプションですが、デフォルトで有効になっています。無効にするには --disable= オプションを使用します。
パイプと gzip コマンドを使用すれば .svg から .svgz に変換もできます(Usage/CLI/with SVGZ)。
GUI ツール SVGOMG
SVGO を GUI で操作できるようにした Web ツール SVGOMG もあります。
SVGOMG のページを開いたら最適化したいファイルをドラッグ&ドロップするだけで最適化してくれます。またはファイルをアップロードしたり、直接コードをペーストすることもできます。
ファイルをドラッグ&ドロップすると、IMAGE タブでページの右側に各種オプションの有効・無効のボタンがあるので画像を確認しながら操作ができます。
MARKUP タブを選択すると、コードが表示されるので、オプションの変更をリアルタイムで確認できます。以下は xmlns 属性の削除を有効にした場合の例です。
webpack 用のローダー
webpack で SVG を最適化する webpack 用のローダーもあるようです(まだ試していません)。
svg 要素(svg タグ)
HTML5 では svg 要素を body 要素の中に直接記述して SVG を埋め込むことができます(HTML の中に SVG のコードをインラインで記述するのでインライン SVG と呼ぶこともあります)。
svg 要素は SVG のルート要素で、SVG 関連の要素を格納するための要素です。ちなみに HTML のルート要素は html 要素です。
別の言い方をすると、svg 要素は HTML と svg の 境目となる要素で svg 要素の配下には基本的には SVG で定義された(SVG 関連の)要素を記述します。
SVG 記述上の注意点
SVG は XML で定義されている言語なので HTML と異なる部分があります。
- SVG では要素名や属性名の大文字・小文字を区別します。例えば viewBox 属性は viewbox では機能しません(jQuery の setAttribute() は自動的に小文字に変換するので注意が必要です)。
- 閉じタグがないタグでは "/>" で終了します(必要な "/>" の記述を忘れると、例えば以降の要素が表示されないなど問題が出ます)。
以下は SVG で円を表示する記述の例です。
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" viewBox="0 0 200 100" style="background-color:lightblue; "> <circle cx="100" cy="50" r="40" stroke="white" stroke-width="5" fill="yellow"/> </svg>
svg 要素にインラインスタイルで薄青色の背景色を指定し、circle SVG 要素で半径 40px の白枠で塗りが黄色の円を表示しています。
HTML5 でのインライン SVG の場合、svg 要素のほとんどの属性は省略することができます。
以下は svg 要素を div 要素でラップして、div 要素に背景色と幅と高さを指定して、上記とほぼ同じように表示する例です。circle SVG 要素は同じです。
<div style="width: 200px; height: 100px; background-color: lightblue;"> <svg viewBox="0 0 200 100"> <circle cx="100" cy="50" r="40" stroke="white" stroke-width="5" fill="yellow"/> </svg> </div>
以下でもほぼ同じになります。
<svg width="200" height="100" style="background-color:lightblue; "> <circle cx="100" cy="50" r="40" stroke="white" stroke-width="5" fill="yellow"/> </svg>
svg 要素の属性
以下は svg 要素の主な属性です。
属性 | 意味 |
---|---|
xmlns | svg 要素の配下で SVG 固有のタグを利用するために SVG 名前空間 "http://www.w3.org/2000/svg" を宣言します。HTML5 ではインライン SVG の場合、ブラウザー側が自動で解釈してくれるので省略可能。 |
xmlns:xlink | XLink 名前空間宣言。xmlns:xlink="http://www.w3.org/1999/xlink" のように指定。HTML5 インライン SVG の場合、省略可能。 |
version | 要素内で使用する SVG のバージョンを指定(省略可能)。現時点での最新バージョンは 1.1(version="1.1")。※ SVG 2 では非推奨 |
width | svg 要素を表示する幅(SVG 内容が描画される矩形領域:ビューポートの幅)。レスポンシブにする場合や CSS で指定する場合は不要。 |
height | svg 要素を表示する高さ(SVG 内容が描画される矩形領域:ビューポートの高さ)。 レスポンシブにする場合や CSS で指定する場合は不要。 |
viewBox | 描画する図形の座標系(SVG の描画領域)を定義する属性で、viewBox="min-x, min-y, width, height" のように4つの値(X座標の最小値, Y座標の最小値, 幅, 高さ)を単位を付けずに、半角スペースまたはコンマで区切って指定します。指定を省略した場合は、左上隅を(0, 0)として width と height で指定された範囲が表示されます。 |
preserveAspectRatio | 異なるアスペクト比での表示時に、SVG(ドキュメントフラグメント) がどう変形されるかを指定できます。初期値: xMidYMid meet |
x | SVGコンテナが表示される x 座標。svg 要素内に svg 要素を配置する場合に指定(最も外側の svg 要素では効果ありません)。 |
y | SVGコンテナが表示される y 座標。svg 要素内に svg 要素を配置する場合に指定(最も外側の svg 要素では効果ありません)。 |
グローバル属性 | class や id、style、tabindex などのグローバル属性(HTML 要素に共通の属性)を必要に応じて指定できます。 |
width と height
svg 要素の width と height 属性はブラウザ上での表示サイズを表し、単位には px、em、ex、pt、pc、cm、mm、in、% が使用できます。
レスポンシブにする(親要素の大きさにより可変にする)場合や CSS で指定する場合は指定しません。
viewBox
SVG には、ビューポート(SVG viewport)とビューボックス(viewBox)という概念があります。
ビューポートは SVG コンテンツの表示領域のことで、その大きさ(サイズ:幅と高さ)は svg 要素の width と height 属性で指定します。
ビューボックスはコンテンツの表示領域(ビューポート)の中の svg の描画領域(どこからどこまでをどのようなアスペクト比で収めるか)を定義するもので、svg 要素の viewBox 属性で指定します。
描画領域の定義では、左上隅を原点 (0, 0) として右方向へ伸びる X 軸と下方向へ伸びる Y 軸を持つ座標を使います。
以下は幅400px、高さ300pxの svg の表示領域(ビューポート)に半径50pxの円を表示する例です。
表示領域の背景にはピンク色を、円には薄青色の背景色と青の枠線を設定していますがコード上では省略しています。
<svg width="400" height="300" viewBox="0 0 400 300" > <circle cx="200" cy="150" r="50"/> </svg>
svg 要素の width="400" height="300" は表示領域(ビューポート)の幅と高さです。
viewBox 属性は viewBox="0 0 400 300" のように4つの値を単位を付けずに、半角スペースまたはコンマで区切って指定します。
viewBox="min-x, min-y, width, height"
- min-x :左上のX座標の値(X座標の最小値)
- min-y :左上のY座標の値(Y座標の最小値)
- width :描画領域の幅
- height :描画領域の高さ
circle 要素は円を定義する要素で、以下が指定している属性です。
- cx 中心のX座標
- cy 中心のY座標
- r 半径
上記の svg は以下のように表示されます。
この例の場合、viewBox の左上の座標は 0 0 で、描画領域の幅は 400、高さは 300 で表示領域(ビューポート)と一致しています。
以下のようにビューボックスを viewBox="150 130 200 150" と指定すると、座標(150,130)から座標(350,280)の範囲を svg 要素の表示領域 width="400" height="300" に表示します。
この例の場合 200x150 の領域を 400x300 で表示するので拡大して見えることになります。
SVG の座標系は特定の絶対単位を持たないため、単位のサイズはビューポートの大きさと viewBox で指定した幅と高さによって異なってきます。
この例の場合は 1座標 = 2px になります。前述の例のように viewBox の幅と高さを表示領域(ビューポート)の幅と高さに一致するようにすると、1pxを1座標(1座標 = 1px)として扱えます。
<svg width="400" height="300" viewBox="150 130 200 150"> <circle cx="200" cy="150" r="50" stroke-width="5"/> </svg>
以下は上記の例のビューボックスと同じサイズと位置の四角形の枠線を rect 要素で表示する例です。
<svg width="400" height="300" viewBox="0 0 400 300"> <circle cx="200" cy="150" r="50"/> <rect x="150" y="130" width="200" height="150" stroke="red" stroke-width="2" fill="none"/> </svg>
以下は viewBox="150 130 200 150" を指定した場合の実際の表示例です。
<svg width="400" height="300" viewBox="150 130 200 150"> <circle cx="200" cy="150" r="50"/> </svg>
preserveAspectRatio
前述の例では表示領域(ビューポート)の幅と高さ(400x300)と viewBox の幅と高さ(200x150)が同じ縦横比の 4:3 でしたが、以下は viewBox の幅と高さを 200x200 に指定した場合の例です。
<svg width="400" height="300" viewBox="150 130 200 200"> <circle cx="200" cy="150" r="50"/> </svg>
表示領域(ビューポート)と viewBox の縦横比が異なる場合、preserveAspectRatio 属性で描画方法を指定することができます。デフォルトでは xMidYMid meet という値が設定されていて、上のように縦横比を変えず左右上下が中央にくるように描画されます。
preserveAspectRatio の値を none に指定すると以下のような表示になります。
<svg width="400" height="300" viewBox="150 130 200 200" preserveAspectRatio="none"> <circle cx="200" cy="150" r="50"/> </svg>
関連項目:preserveAspectRatio
viewBox 確認サンプル
以下は viewBox の値や表示領域のサイズを変更してどのように見えるかを確認するサンプルです。
初期表示の状態では、表示領域(ビューポート)の大きさは幅:400px、高さ:300px で、ビューボックスの値は viewBox="0 0 400 300" です。
スライダーでそれぞれの値を変更して円の位置や大きさの変化を確認することができます。
赤枠の四角形は、ビューボックスのガイドとして使うことを想定しています。
赤枠の四角形の位置(x,y)や幅と高さを変更して「Apply」ボタンを押すと、四角形の位置と幅と高さを svg 要素の viewBox の値に適用して表示します。
例えば初期表示の状態で「Apply」ボタンを押すと、svg 要素の viewBox の値を 100 100 200 150 にして表示します。
svg 要素と四角形の縦横比が同じであれば、「Apply」ボタンを押すと四角形は表示領域いっぱいに広がります。縦横比が異なる場合は preserveAspectRatio のプルダウンで、none を選択すると四角形は表示領域いっぱいに広がりますが円は楕円になります。
overflow で visible を選択すると svg 要素に overflow: visible が適用され表示領域外も表示されます。
赤枠の四角形を非表示にするには、四角形の幅または高さを0にします。Reset ボタンを押すと初期表示の状態に戻ります。
<svg width="0 0 " preserveAspectRatio="xMidYMid meet" > <circle cx="200" cy="150" r=" " stroke-width="5"/> <rect x="100" y="100" width=" " height=" "/> </svg>" height=" " viewBox="
preserveAspectRatio
基本図形要素
基本的な図形を描画するための以下のような基本図形要素が用意されています。
- rect(四角形)
- circle(正円)
- ellipse(楕円)
- line(直線)
- polyline(ポリライン/折れ線)
- polygon(多角形)
- path(パス)
それぞれの要素には固有の属性(専用属性)があります。
また、SVG 図形の塗りや線の色など図形の見た目(スタイル)は属性(プレゼンテーション属性)や CSS で設定することができます。
基本図形要素の記述上の注意点
基本図形要素のタグには閉じタグがないので、タグは "/>" で終了します。 ※訂正:閉じタグはあります。
基本図形要素の場合、子要素を持たないことが多いので閉じタグを使わずにタグは "/>" で終了することが多いです。
<!-- 子要素がない場合は以下のように / で閉じます --> <rect x="20" y="20" width="80" height="60" /> <!-- 子要素がない場合でも以下のように記述することもできます --> <rect x="20" y="20" width="80" height="60"></rect> <!-- 子要素(アニメーションの animate 要素など)がある場合 --> <rect x="20" y="20" width="80" height="60"> <animate ... /> </rect>
閉じタグを使わない場合、最後のスラッシュ("/>")の記述を忘れると、それ以降の要素が表示されません。以下の場合は、最初の rect 要素で閉じるための / を忘れているので、最初の rect 要素は表示されますが、以降の circle 及び ellipse 要素が表示されません。
<svg width="300" height="100" viewBox="0 0 300 100"> <!-- 最初の rect 要素で閉じるための / を忘れている --> <rect x="20" y="20" width="80" height="60"> <!-- 以降の要素が表示されない --> <circle cx="140" cy="50" r="30"/> <ellipse cx="220" cy="50" rx="40" ry="25"/> </svg>
以降のサンプルのコード
以降の例では、表示領域がわかりやすいように svg 要素に style 属性で背景色を指定(例 style="background-color: lightblue;")していますが、サンプルのコードでは省略しています。
rect(四角形)
rect 要素を使って左上の座標(x,y)及び幅と高さを指定すること四角形を描画することができます。
<rect x="50" y="50" width="100" height="60" rx="10" ry="10"/>
属性 | 意味 |
---|---|
x | 左上の x 座標 |
y | 左上の y 座標 |
width | 幅 |
height | 高さ |
rx | 角の丸みの x 方向(横方向)の半径(x-axis radius)。rx または ry の片方しか指定されていない場合は、その値が両方に適用されます。また rx、ry の両方またはどちらかの値が 0 の場合は角丸になりません(ブラウザによってはどちらかが0でも角丸になります)。 |
ry | 角の丸みの y 方向(縦方向)の半径(y-axis radius) |
以下は幅 600px、高さ100px の表示領域に6つの四角形を描画する例です。
fill で塗りを指定しなければ図形は黒で表示されます。
2番目の正方形は、fill="none" で塗り潰さないようにしています。但し、fill="none" を指定してしまうとマウスイベント等が図形上で発生しなくなるので、それを防ぐには3番目のように rgba(0,0,0,0) (黒の透明)や transparent を指定します。
左の2つの正方形の y 座標は 0 にしてあります。2つ目の正方形の上辺のストロークの幅が狭いのは、ストロークはパスの周りに中央揃えで置かれるため、上半分が表示領域外に出てしまっているためです。3つ目以降の図形の y 座標は 4 にしてストロークが全て表示されるように配置しています。
3番目の正方形の ry は省略しているので、rx の値が適用されます。
但し、rx または ry どちらかの値が 0 の場合は角丸になりません。
半径の値を辺の長さの半分以上にすると rect 要素で円や楕円を描画することができます。circle 要素や ellipse 要素は中心を描画の基準とするのに対して、rect 要素は左上を描画の基準とする点が異なります。
<svg width="600" height="100" viewBox="0 0 600 100"> <rect x="0" y="0" width="80" height="80"/> <rect x="100" y="0" width="80" height="80" stroke="black" stroke-width="8" fill="none"/> <rect x="200" y="4" width="80" height="80" rx="10" stroke="black" stroke-width="8" fill="rgba(0,0,0,0)"/> <rect x="300" y="4" width="80" height="80" rx="20" ry="40" stroke="black" stroke-width="8" fill="lightblue"/> <rect x="400" y="4" width="80" height="80" rx="40" ry="40" stroke="black" stroke-width="8" fill="pink"/> <rect x="500" y="4" width="80" height="40" rx="40" ry="40" stroke="black" stroke-width="8" fill="yellow"/> </svg>
レスポンシブ
実際には上記の例は以下のように svg 要素には width と height を指定せず、その親要素に max-width を指定して画面幅により伸縮するようにしています。
<div style="max-width: 600px"> <svg viewBox="0 0 600 100" style="background-color:lightgreen"> <rect x="0" y="0" width="80" height="80"/> ・・・省略・・・ </svg> </div>
circle(正円)
circle 要素を使って中心の座標(cx,cy)と半径(r)を指定することで円を描画することができます。
<circle cx="40" cy="40" r="40"/>
属性 | 意味 |
---|---|
cx | 円の中心の x 座標 |
cy | 円の中心の y 座標 |
r | 円の半径(radius) |
2つ目の円は中心の y 座標(cy)を半径の値に指定していますが、ストロークはパスの周りに中央揃えで置かれるため、上半分が表示領域外に出てしまっています。
<svg width="300px" height="100px" viewBox="0 0 300 100"> <circle cx="40" cy="40" r="40"/> <circle cx="150" cy="40" r="40" stroke="black" stroke-width="10" fill="transparent"/> <circle cx="250" cy="50" r="40" stroke="black" stroke-width="10" fill="lightyellow"/> </svg>
ellipse(楕円)
ellipse 要素を使って中心の座標(cx,cy)と X 軸及び Y 軸方向の半径(rx, ry)を指定することで楕円を描画することができます。
<ellipse cx="100" cy="50" rx="100" ry="50"/>
属性 | 意味 |
---|---|
cx | 楕円の中心の x 座標 |
cy | 楕円の中心の y 座標 |
rx | 楕円の X 軸方向の半径 |
ry | 楕円の Y 軸方向の半径 |
1つ目の楕円は中心の x 座標を0にしているので左半分は表示領域の外に出ています。
3つ目と4つ目の楕円は中心の座標を同じにしてあるので中心で重なり、後から記述されている4つ目の楕円が前面に表示されます。
5つ目の楕円は X 軸及び Y 軸方向の半径を同じにしているので正円になっています。
<svg width="600px" height="100px" viewBox="0 0 600 100"> <ellipse cx="0" cy="50" rx="100" ry="50"/> <ellipse cx="200" cy="50" rx="80" ry="40" stroke="gray" stroke-width="8" fill="lightblue"/> <ellipse cx="380" cy="50" rx="80" ry="40" stroke="lightblue" stroke-width="8" fill="lightgreen"/> <ellipse cx="380" cy="50" rx="40" ry="20" stroke="orange" stroke-width="6" fill="yellow"/> <ellipse cx="540" cy="50" rx="40" ry="40" stroke="gold" stroke-width="8" fill="silver"/> </svg>
line(直線)
line 要素を使って始点(x1,y1)と終点(x2,y2)の座標を指定することで直線を描画することができます。
<line x1="0" y1="0" x2="100" y2="50" stroke="black" stroke-width="5"/>
属性 | 意味 |
---|---|
x1 | 始点の x 座標 |
y1 | 始点の y 座標 |
x2 | 終点の x 座標 |
y2 | 終点の y 座標 |
1つ目のラインは y 座標が同じなので水平のライン、2つ目のラインは x 座標が同じなので垂直のラインになります。
<svg width="320px" height="100px" viewBox="0 0 320 100" > <line x1="10" y1="10" x2="90" y2="10" stroke="black" stroke-width="5"/> <line x1="100" y1="10" x2="100" y2="90" stroke="yellow" stroke-width="5"/> <line x1="110" y1="90" x2="200" y2="10" stroke="red" stroke-width="5"/> <line x1="210" y1="10" x2="300" y2="90" stroke="blue" stroke-width="5"/> </svg>
polyline(ポリライン/折れ線)
polyline 要素を使って頂点の座標(x,y)のリストを指定することで折れ線を描画することができます。
polyline は連結された line(直線)の集まりのようなものです。
指定方法は points 属性に x と y の座標のペアを列挙(リスト)して形状を指定します。
各々の数値は半角スペースや改行などの空白文字やカンマで区切り、各々の点は X 座標と Y 座標の2つの値を持たなければなりません(半角スペース、カンマのどちらかだけでも両方使っても x と y の座標のペアになっていれば問題ありません)。
以下の polyline 要素はいずれも同じ折れ線を描画します。
<polyline points="0,50 50,90 100,50 150,10" stroke="black" stroke-width="5"/> <polyline points="0 50,50 90,100 50,150 10" stroke="black" stroke-width="5";/> <polyline points="0 50 50 90 100 50 150 10" stroke="black" stroke-width="5"/> <polyline points="0,50,50,90,100,50,150,10" stroke="black" stroke-width="5"/> <!-- 線として表示するには fill="none" や fill="transparent" を追加で指定します-->
属性 | 意味 |
---|---|
points | 折線を構成する頂点の座標(x,y)のリスト |
以下は stroke 属性と stroke-width 属性を指定した例です。
fill 属性は指定していませんが、fill 属性の初期値は black なので以下のような表示になります(閉じられていないパスの両端が繋がれて塗りが行われます)
<svg width="320px" height="100px" viewBox="0 0 320 100" > <polyline points="0,50 50,90 100,50 150,10 200,50 200,90 300,90 300,10 250,50" stroke="black" stroke-width="5"/> </svg>
以下は fill="transparent" を指定して「塗なし」にしています。fill="none" でも同じ表示になります。
<svg width="320px" height="100px" viewBox="0 0 320 100" > <polyline points="0,50 50,90 100,50 150,10 200,50 200,90 300,90 300,10 250,50" stroke="black" stroke-width="5" fill="transparent"/> </svg>
以下はそれぞれの頂点の位置に circle 要素で円を追加した例です。
<svg width="320px" height="100px" viewBox="0 0 320 100" > <polyline points="0,50 50,90 100,50 150,10 200,50 200,90 300,90 300,10 250,50" stroke="black" stroke-width="5" fill="transparent"/> <circle cx="0" cy="50" r="5"/> <circle cx="50" cy="90" r="5"/> <circle cx="100" cy="50" r="5"/> <circle cx="150" cy="10" r="5"/> <circle cx="200" cy="50" r="5"/> <circle cx="200" cy="90" r="5"/> <circle cx="300" cy="90" r="5"/> <circle cx="300" cy="10" r="5"/> <circle cx="250" cy="50" r="5"/> </svg>
以下は塗りを黄色に指定しています。
<svg width="320px" height="100px" viewBox="0 0 320 100" > <polyline points="0,50 50,90 100,50 150,10 200,50 200,90 300,90 300,10 250,50" stroke="black" stroke-width="5" fill="yellow"/> </svg>
polygon(多角形)
polygon 要素を使って頂点の座標(x,y)のリストを指定することで多角形を描画することができます。
polygon 要素は前述の polyline 要素と指定方法は同じで、 points 属性に x と y の座標のペアを列挙して多角形の形状を指定します。
polygon 要素と polyline 要素の違いはパスが閉じられるか否かだけで、polygon では自動で始点と終点がつながり、閉じた図形を作成します。
以下は3つの頂点を指定しているので3角形が描画されます。
<polygon points="0,10 50,90 100,10"/>
属性 | 意味 |
---|---|
points | 折線を構成する頂点の座標(x,y)のリスト |
以下は前述の polyline の例と同じ値を指定した例です。始点と終点が自動的につながって閉じた図形が形成されています。
<svg width="320px" height="100px" viewBox="0 0 320 100" > <polygon points="0,50 50,90 100,50 150,10 200,50 200,90 300,90 300,10 250,50" stroke="black" stroke-width="5" fill="yellow"/> </svg>
以下は10この頂点を持つ星型の図形です。
<div style="max-width: 120px"> <svg viewBox="0 0 300 300"> <polygon points="150,35 179,121 269,121 197,175 223,261 150,210 77,261 103,175 31,121 121,121" stroke="black" stroke-width="2" fill="yellow"/> </svg> </div>
以下は上記と同じ星型の図形を一筆書きのように5つの頂点で作成したものです。以下の場合、塗りつぶし方法の属性 fill-rule に evenodd を指定しているため真ん中の部分が白抜き(塗りなし)になっています。
<div style="max-width: 120px"> <svg viewBox="0 0 300 300"> <polygon points="150,35 223,261 31,121 269,121 77,261" fill-rule="evenodd" stroke="black" stroke-width="2" fill="yellow"/> </svg> </div>
path(パス)
path 要素を使うと任意の図形を描画することができます。
前述の基本的な図形要素は全て path 要素で描画することができますが、単純な図形は基本的な図形要素で描画する方が簡単です。path 要素を使えば複雑な図形を描画することができます。
path 要素は d 属性を使って形を指定(定義)します。
属性 | 意味 |
---|---|
d | 図形の外形線の定義(path data)を指定します。 |
d 属性にはパスを描画するためのコマンドの文字列(パスデータ)を指定します。
以下は d 属性に設定できるコマンドの概要です。コマンドの後には座標などのパラメータを半角スペース(空白文字)やカンマ区切りで記述します。
全てのコマンドには、その相対版があります。大文字のコマンドは絶対座標(絶対位置指定), 小文字のコマンドは相対座標(現在位置からの相対位置指定)になっています。
コマンド | name | 意味 |
---|---|---|
M m | moveto | パスの開始位置を設定するコマンド(移動コマンド)。開始位置の座標(x,y)を指定します。パスデータはこの移動コマンドで始めます。 後続の移動コマンド(M または m)は新たな部分パスの開始を意味します。 |
L l | lineto | 現在の点から新たな点へ直線を描画するコマンド。新たな点の座標(x,y)を指定します。 |
H h | horizontal lineto | 現在の点から新たな点へ水平線を描画するコマンド。新たな点の x 座標を指定します。 |
V v | vertical lineto | 現在の点から新たな点へ垂直線を描画するコマンド。新たな点の y 座標を指定します。 |
Z z | closepath | 現在の部分パスの終了するコマンド。パラメータはありません。現在の点から現在の部分パスの始点への直線が自動的に描かれます。closepath コマンドの後に moveto コマンドが続く場合、moveto が次の部分パスの始点を指定します。もし closepath の後に他の命令が続く場合、次の部分パスの始点は現在の部分パスの始点と同じになります。 |
C c | curveto | 3次ベジェ曲線を描画するコマンド。始点に対する制御点、終点に対する制御点、終点の3組の座標( x1 y1, x2 y2, x y)を指定します。 |
S s | shorthand/smooth curveto | 3次ベジェ曲線を描画するコマンド。C コマンドなどの前のコマンドで用いた制御点から点対称の位置を新たな制御点として利用することで始点に対する制御点を省略することができる三次ベジェ曲線を描画するコマンドの短縮版。終点に対する制御点、終点の2組の座標( x2 y2, x y)を指定します。 |
Q q | quadratic Bézier curveto | 2次ベジェ曲線を描画するコマンド。始点と終点両方の曲線の傾斜を定義する制御点と終点の2つの座標を(x1 y1, x y)指定します。 |
T t | Shorthand/smooth quadratic Bézier curveto | 2次ベジェ曲線を描画するコマンド。前のコマンドが Q または T コマンドである場合に、終点の座標(x y)を指定すると前のコマンドに用いた制御点を参照して2次ベジェ曲線を描画します。 |
A a | elliptical arc | 楕円形の弧を描画するコマンド。 |
パスデータは読み易くするために改行を入れて複数行にわたらせることができ、余分な空白やコンマなどの区切り文字は省略できます。同じコマンドが続いている場合、後続のコマンドではコマンド文字を省略できます。
基本的なパスの定義
図形(パス)の描画は点から点の間をコマンドで描画していきます。現在の点の位置をカレント座標と呼びます。
最初は移動コマンド(mまたはM)でパスの始点を指定し、カレント座標を図形の始点に移動します。そしてその他のコマンドを使って次の点を指定して図形を描画していきます。
各コマンド実行後のカレント座標はコマンドで指定した終点の座標に移動します。必要に応じて次の図形を連続したパスとして描画できます。
Z(または z)コマンドを実行すると、移動コマンドで指定した始点の座標に自動的に直線が引かれて図形が閉じられます。
大文字のコマンドは絶対座標による指定、小文字のコマンドはカレント座標からの相対座標による指定になります。
<path d="M20,20 v100 h50 l50,-70 h40 v130 l120,-160z" stroke="black" stroke-width="4" fill="#F6C7C8"/>
上記は以下のような図形を描画します(この例の場合、polyline や polygon で作成した方が簡単です)。
- M コマンドで始点(開始位置)を絶対座標 (20,20) に指定
- v コマンドで垂直線を相対座標 100(直前の点から垂直方向に100の位置)に描画
- h コマンドで水平線を相対座標 50(直前の点から水平方向に50の位置) に描画
- l コマンドで直線を相対座標(50,-70)に描画(直前の点からx軸方向に50、y軸方向に-70に描画)
- h コマンドで水平線を相対座標 40 に描画
- v コマンドで垂直線を相対座標 130 に描画
- l コマンドで直線を相対座標(120,-160)に描画
- z コマンドでパスを終了(始点への直線が自動的に描画)
Z コマンドを指定しない場合は折れ線(開いた図形)として扱われます。
<path d="M20,20 v100 h50 l50,-70 h40 v130 l120,-160" stroke="black" stroke-width="4" fill="gold"/>
ベジェ曲線
三次ベジェ曲線は始点と終点に対する2つの制御点をとります。そのため三次ベジェ曲線を作成するには3組(始点に対する制御点、終点に対する制御点、終点)の座標を指定します。
以下は C コマンドを使って三次ベジェ曲線を描画する例です。
C コマンドに指定している最初の座標(70 120)は始点(20 20)に対する制御点で、2つ目の座標(170 120)は終点に対する制御点、最後の3つ目の座標(220 20)は終点です。
<path d="M 20 20 C 70 120, 170 120, 220 20" stroke="black" stroke-width="5" fill="transparent"/>
以下では制御点の値をスライダーで変更してどのような曲線が描画されるかを確認できます。
始点と終点、及び2つの制御点に cirlce で円を、始点と制御点及び終点と制御点を結ぶ線を line で描画しています。
<path d="M 20 20 C 70 120, 170 120, 220 20" stroke="black" stroke-width="5" fill="transparent"/> <circle cx="20" cy="20" r="5" fill="red"/><!-- 始点 --> <circle cx="70" cy="120" r="5" fill="red"/><!-- 始点に対する制御点 --> <line x1="20" y1="20" x2="70" y2="120" stroke="red" stroke-width="2"/> <circle cx="170" cy="120" r="5" fill="red"/><!-- 終点 --> <circle cx="220" cy="20" r="5" fill="red"/><!-- 終点に対する制御点 --> <line x1="170" y1="120" x2="220" y2="20" stroke="red" stroke-width="2"/>
ベジェ曲線をつなげる場合、片方の制御点をもう一方の制御点の対向になるようにすることでなめらかな曲線を描画できます。
S コマンドを使うことで前のコマンドで用いた制御点から点対称の位置を新たな制御点として(始点に対する制御点を省略して)曲線を描画することができます。
以下は C コマンドに続けて S コマンドを使って曲線を滑らかにつなぐ例です。
<path d="M 20 140 C 70 240, 170 240, 220 140 S 270 20, 360 140" stroke="black" stroke-width="5" fill="transparent"/>
以下は上記に始点、制御点、終点とそれらを結ぶ線を追加で描画した例です。
<svg viewBox="0 0 380 280" style="background-color: #C9F9D9;"> <path d="M 20 140 C 70 240, 170 240, 220 140 S 270 20, 360 140" stroke="black" stroke-width="5" fill="transparent"/> <circle cx="20" cy="140" r="5" fill="red"/> <circle cx="70" cy="240" r="5" fill="red"/> <line x1="20" y1="140" x2="70" y2="240" stroke="red" stroke-width="2"/> <circle cx="170" cy="240" r="5" fill="red"/> <circle cx="220" cy="140" r="5" fill="red"/> <line x1="170" y1="240" x2="220" y2="140" stroke="red" stroke-width="2"/> <circle cx="270" cy="20" r="5" fill="red"/> <circle cx="360" cy="140" r="5" fill="red"/> <line x1="270" y1="20" x2="360" y2="140" stroke="red" stroke-width="2"/> </svg>
以下は Q コマンドと T コマンドで2次ベジェ曲線を描画する例です。
Q コマンドでは、始点と終点両方の曲線の傾斜を定義する制御点と終点の2つの座標を(x1 y1, x y)指定します。Q コマンドに続く T コマンドでは終点の座標のみを指定します。
<svg viewBox="0 0 190 160" style="background-color: #C9F9D9;"> <path d="M 10 80 Q 52.5 10, 95 80 T 180 80" stroke="black" stroke-width="5" fill="transparent"/> <!-- 以下は始点、制御点、終点に円とそれらを結ぶ線を追加で描画 --> <circle cx="10" cy="80" r="5" fill="red"/> <circle cx="52.5" cy="10" r="5" fill="red"/> <line x1="10" y1="80" x2="52.5" y2="10" stroke="red" stroke-width="2"/> <line x1="52.5" y1="10" x2="95" y2="80" stroke="red" stroke-width="2"/> <circle cx="95" cy="80" r="5" fill="red"/> <circle cx="135" cy="150" r="5" fill="blue"/><!-- 前の制御点から点対称の位置 --> <circle cx="180" cy="80" r="5" fill="red"/> <line x1="95" y1="80" x2="135" y2="150" stroke="blue" stroke-width="2"/> <line x1="135" y1="150" x2="180" y2="80" stroke="blue" stroke-width="2"/> </svg>
円弧
A コマンドを使うと円や楕円の円周の一部分(円弧)を描画することができます。
以下は L コマンドと A コマンドで斜めの線と2つの円弧を描画する path の例です。
<path d="M 10 315 L 110 215 A 30 50 0 0 1 162.55 162.45 L 172.55 152.45 A 30 50 -45 0 1 215.1 109.9 L 315 10" stroke="black" fill="green" stroke-width="5"/>
A コマンドの書式は以下のようになっていて、最初の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
以下がパラメータの概要です。
パラメータ | 意味 |
---|---|
rx | 水平(X 軸)方向の半径 |
ry | 垂直(Y 軸)方向の半径 |
x-axis-rotation | 回転角(楕円の傾き)。水平(X 軸)方向が0度(360度)で時計回りに増加。 |
large-arc-flag | 円弧の選択。0:短弧(円弧の短い方) 1:長弧(円弧の長い方) |
sweep-flag | 円弧の方向。0:反時計回り 1:時計回り |
x (dx) | 終点の X 座標(dx: 相対座標) |
y (dy) | 終点の Y 座標(dy: 相対座標) |
パラメータの使い方の詳細や A コマンドの概念なことなどについては以下のサイトが参考になります。
path 要素で円を描画
path 要素で閉じた円を描画するには、始点と終点が同じ円弧を描画できないので2つの半円に分けて描画します。
<svg width="120px" height="120px" viewBox="0 0 400 400"> <path d="M 50 200 A 150 150 0 1 1 350 200 A 150 150 0 1 1 50 200" stroke="purple" stroke-width="5" fill="transparent"/> </svg> <!--または--> <svg width="120px" height="120px" viewBox="0 0 400 400"> <path d="M 50 200 a 150 150 0 1 1 300 0 a 150 150 0 1 1 -300 0" stroke="purple" stroke-width="5" fill="transparent"/> </svg>
以下の2つの半円を続けて描画しています。
<svg width="120px" height="120px" viewBox="0 0 400 400" > <path d="M 50 200 A 150 150 0 1 1 350 200" stroke="purple" stroke-width="5" fill="transparent"/> </svg> <svg width="120px" height="120px" viewBox="0 0 400 400"> <path d="M 350 200 A 150 150 0 1 1 50 200" stroke="purple" stroke-width="5" fill="transparent"/> </svg>
A コマンド動作確認サンプル
以下はスライダーで A コマンドのパラメータの値を変更してどのように描画されるかを確認するサンプルで、開始点(M 50 200)は固定になっています。
黄色い文字とガイドラインは x-axis-rotation に指定した値により描画領域の中心(200,200)を軸に回転します。
<svg viewBox="0 0 400 400"> <path d="M 50 200 A 150 150 0 1 1 350 200" stroke="red" fill="transparent"/> </svg> <!-- A コマンド: rx ry x-axis-rotation large-arc-flag sweep-flag x y -->
path 要素と C コマンドでイージング関数(cubic-bezier)のビジュアル化
cubic-bezier 関数は入力値を3次ベジェ曲線に沿って変化させて出力するイージング関数なので、cubic-bezier 関数に指定するパラメータ(引数の値)を path 要素の C コマンドに指定するとビジュアル化することができます。
例えば viewBox="0 0 1 1" とした場合、 M コマンドでパスの開始位置を(0 0)とします。そして C コマンドで始点に対する制御点(x1 y1)と終点に対する制御点(x2 y2 )に対応する値を cubic-bezier 関数のパラメータを指定し、終点(1 1)を指定します。
<path d="M0 0 C x1 y1, x2 y2 1 1"></path>
以下は viewBox="0 0 1 1" として M コマンドでパスの開始位置を(0 0)として、終点(1 1)の間に C コマンドに続けてイージング easeInOutBack の cubic-bezier(0.68, -0.6, 0.32, 1.6) のパラメータ部分を指定しています(カンマは省略できます)。
この例の曲線は外側にはみ出すので、overflow:visible を指定しています。また小さなビューポートに描画しているので、vector-effect="non-scaling-stroke"を指定しています。
<svg width="100" height="100" viewBox="0 0 1 1" style="background-color:yellow; overflow:visible; margin: 40px 0;"> <path d="M 0 0 C 0.68, -0.6, 0.32, 1.6 1 1" fill="none" stroke="black" vector-effect="non-scaling-stroke"></path> </svg>
但し、前述の例の場合、左上隅の原点 (0, 0) から右下(1,1)に向かって描画しているので、パスを左下から右上に描画するには transform を使います(もっと良い方法があるかも知れません)。
この例では、rotate(180, .5, .5) で (0.5, 0.5) を中心に180度回転させ、scale(-1,1) で X 軸方向に反転させ、translate(-1)で移動させています。
<svg width="100" height="100" viewBox="0 0 1 1" style="background-color:yellow; overflow:visible; margin: 40px 0;"> <path d="M 0 0 C 0.68, -0.6, 0.32, 1.6 1 1" transform="rotate(180, .5, .5) scale(-1,1) translate(-1)" fill="none" stroke="black" vector-effect="non-scaling-stroke"> </path> </svg>
以下のように scale(1,-1) で Y 軸方向に反転させた方が簡単ですね(同じ結果になります)。
<svg width="100" height="100" viewBox="0 0 1 1" style="background-color:yellow; overflow:visible; margin: 40px 0;"> <path d="M 0 0 C 0.68, -0.6, 0.32, 1.6 1 1" transform="scale(1,-1) translate(0,-1)" fill="none" stroke="black" vector-effect="non-scaling-stroke"> </path> </svg>
以下は viewBox="0 0 100 100" として、終点を(100 100)として、easeInOutExpo の cubic-bezier(0.87, 0, 0.13, 1) のパラメータの各値を100倍して指定しています。また、この場合は stroke-width にサイズを指定しています。
<svg width="100" height="100" viewBox="0 0 100 100" style="background-color:lightgreen; overflow:visible; margin: 40px 0;"> <path d="M 0 0 C 87, 0, 13, 100 100 100" fill="none" stroke="black" stroke-width="2"></path> </svg>
以下は前述の例と同様、パスを左下から右上に描画する場合の例です。translate の移動距離に指定する値もサイズに合わせて調整します。scale は同じ大きさで反転させるだけなので指定する値は同じです。
<svg width="100" height="100" viewBox="0 0 100 100" style="background-color:lightgreen; overflow:visible; margin: 40px 0;"> <path d="M 0 0 C 87, 0, 13, 100 100 100" transform="scale(1,-1) translate(0,-100)" fill="none" stroke="black" stroke-width="2"></path> </svg>
以下でも同じです。
<svg width="100" height="100" viewBox="0 0 100 100" style="background-color:lightgreen; overflow:visible; margin: 40px 0;"> <path d="M 0 0 C 87, 0, 13, 100 100 100" transform="rotate(180, 50, 50) scale(-1,1) translate(-100)" fill="none" stroke="black" stroke-width="2"> </path> </svg>
テキスト
text 要素を用いて SVG ドキュメントに任意のテキストを入れることができます。
<svg width="240px" height="50px" viewBox="0 0 240 50" style="border: 1px solid #ccc;"> <circle cx="0" cy="0" r="40" fill="gold"/> <text x="30" y="35" fill="lightgreen" stroke="green" font-family="Verdana" font-size="30">Hello World!</text> </svg>
tref 要素(参考)
定義しているテキストを参照する tref 要素は SVG2 で削除されたため、現在ブラウザではサポートされていません。
Remove TREF from the SVG 2 spec / Removed the 'tref' element.
text 要素
text 要素は x と y 属性でビューポート(表示領域)のどこにテキストを表示するかを指定します。
図形の要素と同様、テキストも fill 属性による塗りと、stroke 属性によるストロークの指定ができます。
属性 | 意味 |
---|---|
x | テキスト(最初の文字)の X 座標(水平方向の位置)を指定。数値のリストを指定すると、その値は一つずつ、text 要素内の各文字に適用されます。 |
y | テキスト(最初の文字)の Y 座標(垂直方向の位置)を指定。数値のリストを指定すると、その値は一つずつ、text 要素内の各文字に適用されます。 |
dx | 現在のテキスト位置 を X 軸方向にずらす量(差分)を指定。x 同様、各文字に適用される値のリストを持つことができます。 |
dy | 現在のテキスト位置 を Y 軸方向にずらす量(差分)を指定。y 同様、各文字に適用される値のリストを持つことができます。 |
rotate | 文字の回転角度を指定。数値のリストを指定すると、それぞれの文字が指定した値の分だけ回転し、残った文字は直前の文字に指定された値に従って回転します。 |
text-anchor | 文字列を設定した座標を基準に相対的に揃えます。 |
テキストの描画は文字の下部(基底線?)を基準に行われるため、以下の場合、フォントサイズが 30 で y 属性が 10 なので文字の上部は描画領域からはみ出してしまいます。
<text x="0" y="10" font-size="30">Hello World!</text>
以下は x 及び y 属性と rotate 属性に数値のリストを指定する例です。指定したリストの座標と回転が各文字に適用されます。
<text x="0 30 70 120 200" y="30 40 25 45 30" rotate="0 30 -30 45 0" font-size="30">Hello</text>
以下は dx、dy属性を使って文字の位置を指定する例です。
x、y属性ではそれぞれの位置を絶対位置として記述しますが、dx、dy属性では本来の位置(前の文字の位置)からの差分で指定することができます。
<text x="30" y="30" dx="0 10 20 30 40" dy="0 5 10 -10 5" font-size="30">Hello</text>
フォントプロパティ
以下の各プロパティを属性または CSS で設定することができます。
- font-family
- font-style
- font-weight
- font-variant
- font-stretch
- font-size
- font-size-adjust
- kerning
- letter-spacing
- word-spacing
- text-decoration
以下はフォントプロパティを属性と CSS(インライン style 属性)の両方で設定した場合の例です。
<text x="30" y="35" font-size="30" text-decoration="underline" style="font-family: 'Comic Sans MS'">Hello World!</text>
writing-mode プロパティ
writing-mode は text 要素に対する初期の行内の文字の進行方向を指定するプロパティで text 要素にのみ適用されます。
以下は writing-mode に指定できる値で、初期値は lr-tb です。
値 | 意味 |
---|---|
lr-tb または lr | 左から右方向(left to right)に文字を配置 |
rl-tb または rl | 右から左方向(right to left)に文字を配置 |
tb-rl または tb | 上から下方向(top to bottom)に文字を配置(縦書き) |
以下は writing-mode に tb を指定して縦書きにする例です。
<text x="20" y="35" font-size="20" writing-mode="tb">Hello World!</text> <text x="60" y="35" font-size="20" writing-mode="tb">ハロー ワールト!</text> <text x="100" y="35" font-size="20" writing-mode="tb">幅 200px の要素</text>
glyph-orientation-vertical
文字並びの角度(行内グリフ方位)を変更するには、glyph-orientation-vertical または glyph-orientation-horizontal プロパティがありましたが、SVG2 では削除されているため、現在ブラウザではサポートされていないようです。
glyph-orientation-vertical: Deprecated since SVG 2
半角英数字の回転
以下の最初の例は tspan 要素で rotate を使って半角の英数字の部分を回転させています。その際、英数字の部分の垂直方向の位置を調整するため dy 属性を使って差分を指定しています。
2つ目の例は x 属性を同じ値にすることで縦書きにしています。各文字には垂直方向に dy 属性を使って差分を指定しています。また、text-anchor に "middle" を指定して中央揃えにしています。
<text x="20" y="20" writing-mode="tb" font-size="20">幅 <tspan dy="20 5 5 10 5" rotate="-90">200px</tspan> の要素 </text> <text x="60 60 60 60 60 60 60 60 60 60 60" y="35" dy="2 10 20 20 20 20 20 20 10 20 20" text-anchor="middle" font-size="20">幅 200px の要素</text>
text-anchor プロパティ
text-anchor プロパティ(属性)を使うと、テキスト文字列を設定した座標を基準に相対的に揃えることができます。
text 要素の文字列のどこを基準に文字列を配置するかを text-anchor を使って指定できます。初期値は start です。
値 | 意味 |
---|---|
start | 先頭揃え。text 要素に設定した座標に先頭を揃える |
middle | 中央揃え。text 要素に設定した座標に中央を揃える |
end | 末尾揃え。text 要素に設定した座標に末尾を揃える |
以下の例では、全ての text 要素の x 属性で X軸上の座標(基準)を 120 に設定しています。基準がわかりやすいように、基準の位置(x : 120)に line 要素で垂直線を描画しています。
<svg width="240px" height="150px" viewBox="0 0 240 150"> <line x1="120" y1="0" x2="120" y2="150" stroke="lightblue"/> <text x="120" y="40" font-size="20" text-anchor="start">Hello World!</text> <text x="120" y="80" font-size="20" text-anchor="middle">Hello World!</text> <text x="120" y="120" font-size="20" text-anchor="end">Hello World!</text> </svg>
水平方向中央揃え
text 要素の x 属性に 50% を指定して、text-anchor 属性に middle を指定すると、水平方向において中央揃えにできます。
<svg width="200px" height="100px" viewBox="0 0 200 100"> <text x="50%" y="58" font-size="20" text-anchor="middle">C</text> <line x1="50%" y1="0" x2="50%" y2="100%" stroke="lightblue"/> <line x1="0" y1="50%" x2="100%" y2="50%" stroke="lightpink"/> </svg>
tspan 要素
tspan 要素は text 要素内の文字列の一部を操作する(扱う)ために使用できます。tspan 要素は text 要素または他の tspan 要素の子要素でなければなりません。
属性 | 意味 |
---|---|
x | テキストの新たな絶対 X 座標を設定。数値のリストを指定した場合は、その値は一つずつ、tspan 要素内の各文字に適用されます。 |
y | テキストの新たな絶対 Y 座標を設定。数値のリストを指定した場合は、その値は一つずつ、tspan 要素内の各文字に適用されます。 |
dx | テキストの描画開始位置を、既定の現在位置から X 軸方向に移動させる差分。各文字に適用される値のリストを持つことができます。 |
dy | テキストの描画開始位置を、既定の現在位置から Y 軸方向に移動させる差分。各文字に適用される値のリストを持つことができます。 |
rotate | 文字の回転角度を指定。数値のリストを指定すると、それぞれの文字が指定した値の分だけ回転し、残った文字は直前の文字に指定された値に従って回転します。 |
以下は text 要素内の文字列を tspan 要素で囲んでフォントのプロパティ(文字色)や位置、回転を調整する例です。
<text x="10" y="30" font-size="30">Hell <tspan fill="red">o</tspan> <tspan x="30" y="80" dx="0 5 5 5 10 20 0 0 20" dy="10 5 10 -20 30 -10 20 0 -10"> <tspan rotate="-20">W</tspan> <tspan fill="blue">o</tspan> rl <tspan rotate="30 60">d!</tspan> </tspan> </text>
textPath 要素
textPath 要素は定義してあるパス(path)を href(または xlink:href)属性で指定して、そのパスに沿って囲むように文字を並べることができます。
属性 | 意味 |
---|---|
xlink:href | path 要素への参照(SVG2 非推奨) |
href | path 要素への参照(推奨されていますが、一部限定的) |
startOffset | 文字配置の開始位置を長さで指定 |
以下は id が my_path のパスに沿って文字列を配置する例です。文字列の開始位置を startOffset で 10 ずらしています。
path の stroke を指定しなければパスを非表示にできます。
<svg width="300px" height="120px" viewBox="0 0 300 120"> <path id="my_path" d="M 20,20 C 70 120, 170 120, 260 20" stroke="gray" fill="transparent"/> <text> <textPath href="#my_path" startOffset="10" fill="green" font-size="22px">This text follows a curve.</textPath> </text> </svg>
以下は tspan で dy を指定して特定の文字の位置を変更する例です。
この例の場合、内側に配置すると文字間隔が狭くなるので文字列 text の部分には letter-spacing を指定して調整しています。
<svg width="300px" height="120px" viewBox="0 0 300 120"> <path id="my_path2" d="M 20,20 C 70 120, 170 120, 260 20" stroke="gray" fill="transparent"/> <text> <textPath href="#my_path2" font-size="22px">This <tspan dy="-30" fill="red" letter-spacing="5">text</tspan> <tspan dy="30">follows</tspan> <tspan dy="20" fill="blue">a</tspan> <tspan dy="-20">curve.</tspan> </textPath> </text> </svg>
以下は直線のパスに沿って文字を並べる例です。
<svg width="300px" height="120px" viewBox="0 0 300 120"> <path id="my_path3" d="M30,30 h100 v60 h120" stroke="silver" fill="transparent"/> <text> <textPath href="#my_path3" font-size="20px" fill="green">This text <tspan rotate="30">f</tspan> ollow <tspan dx="15">s</tspan> <tspan dy="20" rotate="-30">a</tspan> <tspan dx="10" dy="-20">line.</tspan> </textPath> </text> </svg>
関連項目:テキストをパスに沿ってアニメーション
fill と stroke
基本図形や path 要素、text 要素には fill と stroke を使って色を設定(色づけ)することができます。
- fill:オブジェクトの内部への塗り
- stroke:オブジェクトの外形線(outline/縁の線)への塗り
色の指定には色名 (例 red)、RGB 値 (例 rgb(255,0,0))、16進数値(例 #FF0000)、RGBA 値(例 rgba(255,0,0,0.5) )、hsl 値などの HTML で用いる CSS の色の指定と同じ仕組みを使用できます。
<svg width="240px" height="100px" viewBox="0 0 240 100"> <ellipse cx="120" cy="50" rx="100" ry="40" stroke="gray" stroke-width="8" fill="lightblue"/> <text x="120" y="60" stroke="black" fill="#ffffff" font-size="30px" text-anchor="middle">fill と stroke</text> </svg>
opacity
fill-opacity 属性と stroke-opacity 属性
SVG では fill と stroke の不透明度を分けて指定することができ、それぞれ fill-opacity 属性と stroke-opacity 属性で設定します。
<svg width="240px" height="120px" viewBox="0 0 240 120"> <rect x="20" y="20" width="160" height="80" stroke="lightgreen" stroke-width="10" stroke-opacity="0.6" fill="orange"/> <circle cx="180" cy="100" r="50" fill="pink" fill-opacity="0.7" stroke="silver" stroke-width="10"/> </svg>
SVG の stroke は要素の外形線を中心に内と外の両側に描画されるので、stroke-opacity 属性を指定した長方形の塗りの一部が透けて見えています。
opacity 属性は fill と stroke 両方の不透明度をまとめて設定します。
<svg width="240px" height="120px" viewBox="0 0 240 120"> <rect x="20" y="20" width="160" height="80" stroke="lightgreen" stroke-width="10" fill="orange"/> <circle cx="180" cy="100" r="50" fill="pink" opacity="0.5" stroke="silver" stroke-width="10"/> </svg>
fill
fill プロパティはグラフィックス要素(基本図形要素や path、text 要素などの描画される要素)の内部への塗りを設定します。図形の外形線(outline)の内側が塗られる領域になります。
fill での塗りは path 要素内の開いた部分パス(閉じられていないパス)や polyline 要素にも適用されます。
値 | 意味 |
---|---|
none | どのような塗りも適用しない(透明とは異なります)。※注意 |
color 値 | 色キーワード、rgb()、 rgba()、 hsl()、 hsla()、 16進数など |
url(IRI) | グラデーションやパターンの参照 |
currentColor | color 属性(プロパティ)で指定された色を参照 |
fill: none には注意が必要
fill: none; を指定すると塗りの部分に対するイベントも無効になってしまうので注意が必要です。
以下は円に SVG の a 要素を指定してリンクを設定していますが、左側の円には fill="none" を指定してあるので、円にマウスオーバーしてもカーソルはそのままで、円をクリックしても反応しません(ストロークの部分をクリックすると反応します)。
塗りを透明にしてイベントを有効にするには transparent や rgba(0,0,0,0) などを指定します。
<svg width="240px" height="100px" viewBox="0 0 240 100"> <a href="#fill"> <circle cx="50" cy="50" r="40" stroke="blue" fill="none" /> </a> <a href="#fill"> <circle cx="150" cy="50" r="40" stroke="red" fill="transparent" /> </a> </svg>
関連項目:a 要素
以下は Javascript でクリックイベントを設定していますが、左側の を指定した円では円の内部をクリックしても何も起きません(ストロークの部分をクリックすると反応します)。
<svg width="240px" height="100px" viewBox="0 0 240 100"> <circle id="c1" cx="50" cy="50" r="40" stroke="blue" fill="none" /> <circle id="c2" cx="150" cy="50" r="40" stroke="red" fill="rgba(0,0,0,0)" /> </svg> <script> const c1 = document.getElementById("c1"); const c2 = document.getElementById("c2"); c1.addEventListener('click', function() { this.setAttribute('fill', 'lightblue') }); c2.addEventListener('click', function() { this.setAttribute('fill', 'lightpink') }); </script>
fill-rule プロパティ
fill-rule 属性は複数のパスで囲まれる部分がパスの内側かどうかを判定する方法を指定する属性です。内側と判定された部分が塗りつぶされます。
fill-rule 属性の値は nonzero(初期値)または evenodd です。
判定方法は、内側か外側かを判定したい点から何もない領域まで直線を引き、その直線と図形のパスが交わる箇所を調べます。
値 | 意味 |
---|---|
nonzero | 図形のパスが左から右に交わっていたら+1、右から左に交わっていたら-1として、全ての交わった箇所の総和を求めます。結果が0でなければその点は図形の内部と、0であれば図形の外部と判定します。※交わったパスの向きにより結果が異なるので、図形がどのような順で描画されたのかに影響されます。 |
evenodd | 交わった回数が奇数なら図形の内側、偶数なら図形の外側と判定します。※交わったパスの向きは関係ありません。 |
<svg viewBox="0 0 600 300"> <path d="M 150,35 L223,261 L31,121 L269,121 L77,261 z" fill-rule="evenodd" stroke="black" stroke-width="2" fill="yellow"/> <path d="M 450,35 L523,261 L331,121 L569,121 L377,261 L450 35 L569,121 L523,261 L377,261 L331,121z" fill-rule="evenodd" stroke="black" stroke-width="2" fill="yellow"/> </svg>
以下は fill-rule="nonezero" を指定した場合です。
fill-rule="nonezero" を指定した場合、交わったパスの向きにより結果が異なることがあります。
<svg width="200px" height="100px" viewBox="0 0 200 100"> <!-- 左側図形(外側パスが反時計回り、内側パスが反時計周り) --> <path d="M 10 10 V 90 H 90 V 10 Z M 30 30 V 70 H 70 V 30 Z" fill-rule="nonzero" fill="lightgreen" stroke-width="3" stroke="green" /> <!-- 右側図形(外側パスが時計回り、内側パスが反時計回り) --> <path d="M 110 10 H 190 V 90 H 110 Z M 130 30 V 70 H 170 V 30 Z" fill-rule="nonzero" fill="lightgreen" stroke-width="3" stroke="green" /> </svg>
左側の図形は外側パスと内側パスは反時計周りで、内部領域のカウントは -2 になり内側と判定され塗りつぶされます。右側の図形は外側パスが時計回り、内側パスが反時計回りのため、内部領域のカウントは 0 になり外部と判定され塗りが行われないため結果が異なります。
関連項目:path(パス)
stroke
stroke プロパティはオブジェクトの外形線(アウトライン)への塗りを設定(外形線に沿って塗ることを指示)します。基本図形や path 要素、text 要素に指定することができ、値には色(またはキーワード)を指定します。
値 | 意味 |
---|---|
none | どのような塗りも適用しない(塗りなし)。初期値 |
color 値 | 色キーワード、rgb()、 rgba()、 hsl()、 hsla()、 16進数など |
url(IRI) | グラデーションやパターンの参照 |
currentColor | color 属性(プロパティ)で指定された色を参照 |
stroke-width
ストローク(stroke)の幅は stroke-width プロパティで指定します。
値には数値(単位なし)またはパーセントを指定します。パーセント(%)を指定した場合、値は現在のビューポートに対する百分率を表わします。
初期値は 1 です。
値を 0 にすると外形線は描画されません(ストロークされなくなります)。
<svg width="320" height="100" viewBox="0 0 320 100"> <rect x="20" y="10" width="80" height="60" stroke="black" fill="pink"/> <rect x="120" y="10" width="80" height="60" stroke="black" stroke-width="0" fill="pink"/> <rect x="220" y="10" width="80" height="60" stroke="black" stroke-width="10" fill="pink"/> </svg>
stroke と border
stroke で描画される線(アウトライン)は HTML(CSS)の border により描画される枠線(ボーダー)と似ていますが、以下のような違いがあります。
- HTML(CSS)の border
- 要素を囲むように要素の外に描画される
- SVG の stroke
- 要素の外形線(アウトライン:縁の線)を中心に内と外の両側に描画される
border は要素を囲むように要素の外に描画されますが、stroke は要素のアウトラインを中心に内と外の両側に描画されます。
以下は stroke-width が 20 の水平及び垂直の黒色の直線 line に stroke-width が 1 の黄色の line を同じ座標に配置して重ねています。ストロークはパスの両側へ均等に描画されているのがわかります。
<svg width="200px" height="80px" viewBox="0 0 200 80" class="margin_top30"> <!-- 水平のライン(黄)stroke-width="20" --> <line x1="10" y1="10" x2="150" y2="10" stroke="black" stroke-width="20"/> <!-- 水平のライン(黒)stroke-width="1" --> <line x1="10" y1="10" x2="150" y2="10" stroke="yellow" stroke-width="1"/> <!-- 垂直のライン(黄)stroke-width="20" --> <line x1="180" y1="0" x2="180" y2="80" stroke="black" stroke-width="20"/> <!-- 垂直のライン(黄)stroke-width="1" --> <line x1="180" y1="0" x2="180" y2="80" stroke="yellow" stroke-width="1"/> </svg>
以下は circle 要素のアウトラインの不透明度(stroke-opacity)を0.6に設定した例です。アウトラインが透けて塗りの部分が見えています。
stroke-width="20"なので塗りの内側に10px、外側に10pxとなっています。
<svg width="120px" height="120px" viewBox="0 0 120 120"> <circle cx="60" cy="60" r="50" stroke="lightblue" stroke-width="20" stroke-opacity="0.6" fill="pink"/> </svg>
stroke-width 以外にもストロークを操作するための属性があります。
stroke-linecap
stroke-linecap プロパティ(属性)は線の端点のスタイル(形状)を指定します。このプロパティには以下の3つの値を指定できます。
値 | 意味 |
---|---|
butt | ストロークの向きに対して垂直 (90 度) のまっすぐな縁で線を閉じ、縁はパスの終端に一致します。(初期値) |
square | 本質的には butt と同じ外見ですが、ストロークが実際のパスの終端から少しはみ出します。はみ出すストロークの長さは stroke-width の値によります。 |
round | ストロークの終端が丸みを持ちます。ストロークが実際のパスの終端から少しはみ出します。はみ出すストロークの長さは stroke-width の値によります。 |
MDN SVG 属性リファレンス stroke-linecap
<svg width="160px" height="140px" viewBox="0 0 160 140"> <line x1="10" y1="10" x2="150" y2="10" stroke="black" stroke-width="20" stroke-linecap="butt"/> <line x1="10" y1="10" x2="150" y2="10" stroke="pink" stroke-width="1"/> <line x1="10" y1="50" x2="150" y2="50" stroke="black" stroke-width="20" stroke-linecap="square"/> <line x1="10" y1="50" x2="150" y2="50" stroke="pink" stroke-width="1"/> <line x1="10" y1="100" x2="150" y2="100" stroke="black" stroke-width="20" stroke-linecap="round"/> <line x1="10" y1="100" x2="150" y2="100" stroke="pink" stroke-width="1"/> </svg>
stroke-linejoin
stroke-linejoin プロパティ(属性)は、ストロークの角(パスの継ぎ目)をどのように描画するかを制御します。このプロパティには以下の3つの値を指定できます。
値 | 意味 |
---|---|
miter | 一つの角だけが使用される四角形を作成するように、ストロークの線を元の幅のままで少し延長します。(初期値) |
round | miter の動作に加えて、角を丸く描画します。 |
bevel | 面取りして接合します。 |
MDN SVG 属性リファレンス stroke-linejoin
<svg width="300px" height="240px" viewBox="0 0 300 240" class="margin_top30"> <path d="M20,70 L80,20 L140,70" stroke="black" stroke-width="20" stroke-linejoin="miter" fill="transparent"/> <path d="M20,70 L80,20 L140,70" stroke="lightblue" fill="transparent"/> <path d="M20,150 L80,100 L140,150" stroke="black" stroke-width="20" stroke-linejoin="round" fill="transparent"/> <path d="M20,150 L80,100 L140,150" stroke="lightblue" fill="transparent"/> <path d="M20,230 L80,180 L140,230" stroke="black" stroke-width="20" stroke-linejoin="bevel" fill="transparent"/> <path d="M20,230 L80,180 L140,230" stroke="lightblue" fill="transparent"/> </svg>
stroke-miterlimit
stroke-linejoin に miter(初期値)を指定している場合、尖り過ぎと判定されると自動的に面取りが実行されますが、stroke-miterlimit プロパティ(属性)はその上限比率を指定します。初期値は 4 です。
以下の例の場合、面取りを行うかどうかの閾値は 4.1 〜 4.2 の間になっているようです。
stroke-miterlimit に十分に大きな値を指定すれば、面取りが実行されるのを防ぐことができます。
<svg width="300px" height="160px" viewBox="0 0 300 160" class="margin_top30"> <path d="M20,120 L40,40 L60,120" stroke="black" stroke-width="20" stroke-linejoin="miter" fill="transparent"/> <path d="M110,120 L130,40 L150,120" stroke="black" stroke-width="20" stroke-linejoin="miter" stroke-miterlimit="4.2" fill="transparent"/> <path d="M200,120 L220,40 L240,120" stroke="black" stroke-width="20" stroke-linejoin="miter" stroke-miterlimit="4.1" fill="transparent"/> </svg>
stroke-dasharray
stroke-dasharray プロパティ(属性)を指定することで波線状のストロークを描画することができます。
値 | 意味 |
---|---|
none | ダッシュ(破線・点線)を利用しない。(初期値) |
<dasharray> | カンマ/空白区切りの長さのリストでダッシュと間隔の長さを交互に指定します。奇数個の値が与えられた場合、偶数個にするために値のリストが繰り返されます。そのため1つの値を指定すると指定した値の長さのダッシュと間隔の破線になります。 |
MDN SVG 属性リファレンス stroke-dasharray
<svg width="300px" height="165px" viewBox="0 0 300 165"> <!-- 1つ目の点線は2つ目の点線 stroke-dasharray="5 5" と同じこと --> <line x1="0" y1="2.5" x2="240" y2="2.5" stroke-width="5" stroke-dasharray="5" stroke="green"/> <line x1="0" y1="40" x2="240" y2="40" stroke-width="5" stroke-dasharray="5 5" stroke="green"/> <line x1="0" y1="80" x2="240" y2="80" stroke-width="5" stroke-dasharray="5 10" stroke="green"/> <line x1="0" y1="120" x2="240" y2="120" stroke-width="5" stroke-dasharray="10 5" stroke="green"/> <line x1="0" y1="160" x2="240" y2="160" stroke-width="5" stroke-dasharray="5 5 15 5" stroke="green"/> </svg>
角丸
stroke-linecap 属性に round を指定すると、破線を角丸にすることができます。
stroke-linecap 属性に round を指定すると角丸の部分がパスの終端から少しはみ出します。そのため、以下の1つめの例では x 座標の位置で角丸がうまく表示されるように調整しています(はみ出す長さは stroke-width の値により異なります)。
2つ目の例はダッシュの長さを1にしてドットのラインを描画する例です。この場合も角丸の部分がパスの終端から少しはみ出しているため、位置を調整しています。この例の場合は、stroke-dashoffset 属性で開始位置もずらしています。
<svg width="300px" height="100px" viewBox="0 0 300 100"> <line x1="5" y1="5" x2="240" y2="5" stroke-width="10" stroke-dasharray="20 15" stroke="green" stroke-linecap="round"/> <line x1="-15" y1="40" x2="240" y2="40" stroke-width="10" stroke-dasharray="1 20" stroke-dashoffset="1" stroke="green" stroke-linecap="round"/> </svg>
以下は図形のアウトラインを波線状のストロークで描画する例です。。
<svg width="300px" height="100px" viewBox="0 0 300 100"> <circle cx="45" cy="45" r="40" stroke="green" stroke-width="5" stroke-dasharray="10 5" fill="lightgreen"/> <rect x="120" y="5" width="120" height="80" stroke="green" stroke-width="5" stroke-dasharray="20 10" fill="lightgreen"/> </svg>
以下はダッシュの部分の値を大きく指定した例です。
<svg width="300px" height="100px" viewBox="0 0 300 100"> <circle cx="45" cy="45" r="40" stroke="green" stroke-width="5" stroke-dasharray="230 20" fill="lightgreen"/> <rect x="120" y="5" width="120" height="80" stroke="green" stroke-width="5" stroke-dasharray="180 20" fill="lightgreen"/> </svg>
stroke-dashoffset
stroke-dashoffset を使うと、点線の開始位置のオフセット(差分)を指定できます。
<svg width="300px" height="100px" viewBox="0 0 300 100"> <!-- stroke-dashoffset の指定なし --> <rect x="10" y="30" width="120" height="80" rx="10" stroke="green" stroke-width="5" stroke-dasharray="20 15" fill="lightgreen"/> <!-- stroke-dashoffset="15" を指定 --> <rect x="160" y="30" width="120" height="80" rx="10" stroke="green" stroke-width="5" stroke-dasharray="20 15" stroke-dashoffset="15" fill="lightgreen"/> </svg>
以下は stroke-dasharray と stroke-dashoffset の値を変更して動作を確認するサンプルです。
stroke-dashoffset には負の値も指定できます。stroke-dasharray が none の場合は stroke-dashoffset の設定は無効です(意味がありません)。
<svg width="300px" height="40px" viewBox="0 0 300 40"> <line x1="10" y1="20" x2="300" y2="20" stroke="pink" stroke-width="30" stroke-opacity="0.5"/> <line x1="10" y1="20" x2="300" y2="20" stroke="black" stroke-width="10" stroke-dasharray="50 50" stroke-dashoffset="0" stroke-linecap="butt" fill="transparent"/> </svg>
stroke-dasharray | 50 | |
---|---|---|
stroke-dashoffset | 0 | |
stroke-linecap | butt round |
以下は rect 要素を使ったサンプルです。
<svg viewBox="0 0 220 120"> <rect id="stroke_sample2" x="10" y="10" width="200" height="100" rx="10" ry="10" stroke-dasharray="50 50" stroke-dashoffset="0" stroke-linecap="butt" stroke="black" stroke-width="10" fill="pink" fill-opacity="0.5" /> </svg>
stroke-dasharray | 50 | |
---|---|---|
stroke-dashoffset | 0 | |
stroke-linecap | butt round |
以下は stroke-dashoffset を使ったアニメーションの例です。初期状態では stroke-dashoffset の値は 0 で、マウスオーバーすると値を 100 にしています。
<svg width="140px" height="100px" viewBox="0 0 140 100"> <rect class="dashoffset1" x="10" y="10" width="120" height="80" rx="10" stroke="green" stroke-width="5" stroke-dasharray="20 15" fill="lightgreen"/> </svg>
.dashoffset1 { stroke-dashoffset: 0; } .dashoffset1:hover { animation: dash_animation1 1s linear infinite; } @keyframes dash_animation1 { to { stroke-dashoffset: 100; /* 負の値(-100)を指定すると逆方向のアニメーションになります */ } }
マウスオーバーでアニメーション
以下は stroke-dashoffset と stroke-dasharray を使ったアニメーションの例です。初期状態では stroke-dashoffset と stroke-dasharray の値は 600(長方形の周囲の長さ)で、マウスオーバーすると stroke-dashoffset の値を 0 にしています。
<svg width="300px" height="140px" viewBox="0 0 300 140"> <rect class="dashoffset2" x="20" y="5" width="200" height="100" stroke="green" stroke-width="5" fill="lightgreen"/> </svg>
.dashoffset2 { stroke-dasharray: 600; stroke-dashoffset: 600; } .dashoffset2:hover { animation: dash_animation2 2s linear both; } @keyframes dash_animation2 { 0% { stroke-dashoffset: 600; stroke-dasharray: 600; } 100% { stroke-dashoffset: 0; } }
マウスオーバーでアニメーション
JavaScript の getTotalLength()
path などの複雑な図形の stroke の長さは JavaScript の getTotalLength() を使うと簡単に取得できます。上記の例の場合は長方形なので stroke の長さは幅と高さから簡単にわかりますが、以下のように取得することもできます。
//svg 要素の id 属性の値を指定 let rect = document.getElementById('dashoffset_rect'); //要素の周囲の長さ let length = rect.getTotalLength(); console.log(length); //600 上記の rect 要素の場合
以下は getTotalLength() を使って path の長さを取得して jQuery で stroke-dashoffset と stroke-dasharray の値に設定する例です。
CSS の transition を使って svg の親要素の div 要素にマウスオーバーすると stroke-dashoffset の値を0にしてアニメーションする例です。
<div class="path_wrapper"> <svg width="103px" height="130px" viewBox="-1.5 -5 103 130"> <path id="spade" d="M1.095,69.304 C7.342,45.969 44.808,22.940 49.978,-0.001 C49.982,0.014 49.986,0.032 49.990,0.047 C49.994,0.032 49.999,0.014 50.003,-0.001 C55.172,22.940 92.638,45.969 98.886,69.304 C107.348,100.913 65.391,112.564 52.529,88.111 C59.365,111.078 77.648,123.001 77.648,123.001 L22.332,123.001 C22.332,123.001 40.712,111.181 47.504,88.014 C34.703,112.596 -7.379,100.955 1.095,69.304 Z"/> <text x="15" y="70" font-size="12">mouse over</text> </svg> </div>
.path_wrapper { width: 120px; background-color:rgba(241,204,247,0.4); } path#spade{ fill: transparent; stroke: mediumpurple; stroke-width: 3; transition:all 1s; } .path_wrapper:hover path#spade{ /* ホバー時に stroke-dashoffset の値を0に */ stroke-dashoffset:0 !important; }
let path = document.getElementById("spade"); //path の周囲の長さ let length = path.getTotalLength(); //stroke-dashoffset と stroke-dasharray に path の周囲の長さを設定 $("#spade").css({ "stroke-dashoffset":length, "stroke-dasharray":length });
参考サイト:
スタイルの設定
SVG 図形の見た目(スタイル)を定義するプロパティをスタイル付けプロパティと呼び、CSS と共通のプロパティが多くありますが、SVG 独自のプロパティもあります。
SVG で使用できる CSS のプロパティは、HTMLで使用するものとは異なるものもあります。
スタイル付けプロパティで対応する同じ名前の SVG の属性(スタイルを定義する属性)をプレゼンテーション属性と呼びます。これらの属性は図形要素に直接記述することができます。
SVG 図形のスタイルを設定するには大きく分けると以下の2つの方法があります。
- プレゼンテーション属性(presentation attributes)を使って設定
- CSS(スタイルシート)を使って設定
参考:SVG 1.1 スタイル付け ( SVG 1.1 Styling )
以下はいずれも枠線がオレンジ色で塗り色が黄色の円を描画します。
<!-- プレゼンテーション属性で設定 --> <svg width="160px" height="160px" viewBox="0 0 160 160"> <circle cx="80" cy="80" r="40" fill="yellow" stroke="orange" stroke-width="5"/> </svg> <!-- CSS で設定(インラインスタイル) --> <svg width="160px" height="160px" viewBox="0 0 160 160"> <circle cx="80" cy="80" r="40" style="fill:yellow; stroke:orange; stroke-width:5"/> </svg> <!-- CSS で設定(SVG 内容に style 要素を埋め込む例) --> <svg class="sample" width="160px" height="160px" viewBox="0 0 160 160"> <style type="text/css"> .sample circle { fill: yellow; stroke: orange; stroke-width: 5; } </style> <circle cx="80" cy="80" r="40"/> </svg>
スタイルの優先順位
プレゼンテーション属性として設定した値とスタイルシート(CSS)で設定した値とではスタイルシート(CSS)で設定した値が優先されます。
<svg width="160px" height="160px" viewBox="0 0 160 160"> <circle id="sample_c1" cx="80" cy="80" r="40" fill="yellow" stroke="orange" stroke-width="5"/> </svg>
#sample_c1 { fill: lightgreen; /* 塗りを薄緑 */ stroke: green; /* 線を緑色 */ }
スタイルシート(CSS)で設定した値(薄緑と緑)が優先されます。
プレゼンテーション属性
プレゼンテーション属性を使ってスタイルを設定するには図形要素に fill="yellow" のように「属性="値"」の形式で指定します。指定した図形要素にスタイルが適用されます。
以下はプレゼンテーション属性の fill(塗り)や stroke(ストローク/線の色)、 stroke-width(ストロークの太さ)、 opacity(不透明度)を使ってスタイルを設定する例です。
<svg width="320px" height="240px" viewBox="0 0 320 180"> <circle cx="80" cy="80" r="40" fill="lightblue" stroke="blue" stroke-width="5"/> <rect x="80" y="70" width="100" height="60" stroke="red" stroke-width="3" fill="pink" opacity="0.7"/> <circle cx="80" cy="80" r="20" fill="yellow" stroke="orange" stroke-width="5"/> </svg>
図形の配置(座標)が重なる場合、後から記述されたものが前に表示されます。
どのようなプレゼンテーション属性があるかは以下で確認することができます。
CSS でスタイルを設定
CSS でスタイルを設定するには以下のような方法があります。通常の HTML で CSS を設定するのとほぼ同じように指定することができます。但し、3番目の SVG の style 要素を使う方法はは少し特殊です。
- 外部スタイルシートを参照
- style 属性を使って記述(インライン CSS)
- SVG の style 要素を使って設定
外部スタイルシートを参照
以下は外部スタイルシート(例: style.css)にスタイルを記述して、SVG を記述している HTML でそのスタイルシートを link タグで読み込む場合の例です。
スタイルの設定はスタイルシートを読み込んでいる HTML 全体で有効です。
.sampleX circle { fill: pink; stroke: lightblue; stroke-width: 10; }
sampleX クラスの circle 要素に上記のスタイルを設定。
外部スタイルシートの代わりに、<head> 内で HTML の style 要素を使って記述しても同じです。
<svg class="sampleX" width="100px" height="100px" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="30"/> </svg>
style 属性を使って設定
図形要素にインラインで style 属性を使って指定することができます。プレゼンテーション属性での指定と同様、指定した個別の要素にスタイルが適用されます。
<svg class="sampleX" width="100px" height="100px" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="30" style="fill:lightcoral; stroke:lightpink; stroke-width:10;"/> </svg>
SVG の style 要素を使って設定
SVG の style 要素を使って SVG に直接埋めこむことができます。SVG の style 要素は対応する HTML の style 要素と同一の属性を持っています。
HTML の style 要素の場合、body 要素内に記述すると W3C の Markup Validation Service ではエラーになりますが(ブラウザは表示してくれますが)、SVG の style 要素は問題ありません。
style 要素の内容は CDATA ブロック(<![CDATA[ ... ]]>)内に記述することが推奨されています(">" などの文字の誤認を防ぐため)。HTML5 のインライン SVG では CDATA ブロックを省略しても大丈夫のようですが。
この方法の場合、svg 要素の中に記述しますが、外部スタイルシートや head 内の style 要素に設定するのと同様に設定したスタイルはそのページ全ての図形要素に適用されます。
<svg class="sample" width="100px" height="100px" viewBox="0 0 100 100"> <style type="text/css"><![CDATA[ /* CDATA ブロック内に記述 */ .sample circle { fill: silver; stroke: gold; stroke-width: 10 } ]]></style> <circle cx="50" cy="50" r="30"/> </svg> <!-- 以下は CDATA ブロックを省略した場合の例 --> <svg class="sample" width="100px" height="100px" viewBox="0 0 100 100"> <style type="text/css"> .sample circle { fill: silver; stroke: gold; stroke-width: 10 } </style> <circle cx="50" cy="50" r="30"/> </svg>
currentColor キーワード
currentColor は要素の color プロパティの値を表すキーワードで、fill や stroke などで使用することができます。また、CSS にも同じキーワード currentColor があります。
currentColor キーワードを使って親の要素の色を参照することができます。
以下は svg 要素の親要素(div 要素)と svg 要素に color を設定して、その子要素で currentColor キーワードを使って色を参照する例です。
1つ目の円は親要素の div 要素の CSS color プロパティを参照し、2つ目の円は直接の親要素の svg 要素の CSS color プロパティを参照します。
<!--svg 要素の親要素である div 要素に color(緑)を設定--> <div style="color: green"> <svg width="100px" height="100px" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="40" stroke="currentColor" stroke-width="10" fill="currentColor" fill-opacity="0.5"/> </svg> <!--svg 要素に color(オレンジ)を設定--> <svg width="100px" height="100px" viewBox="0 0 100 100" style="color: orange"> <circle cx="50" cy="50" r="40" stroke="currentColor" stroke-width="10" fill="currentColor" fill-opacity="0.5"/> </svg> </div>
HTML の要素に CSS の color プロパティが設定されている場合、svg 要素内の図形の色の指定でその色を currentColor で参照できます。
そのため、HTML の文字列と svg 要素の色をまとめて設定することができます。
以下は div 要素の color プロパティで色を指定して、その色を svg 要素内の図形やテキストで参照する例です。:hover を div 要素に指定してあるのでマウスオーバーすると色が変化します。
<div class="foo"> <p>HTML paragraph text.</p> <svg width="140px" height="100px" viewBox="0 0 140 100"> <ellipse cx="65" cy="30" rx="50" ry="20" stroke="currentColor" stroke-width="5" fill="currentColor" fill-opacity="0.3"/> <text x="50" y="35" fill="currentColor">ABC</text> <line x1="20" y1="80" x2="120" y2="80" stroke="currentColor" stroke-width="24" stroke-linecap="round"/> <text x="50" y="85" fill="white">text</text> </svg> </div>
.foo { color:purple; border: 1px solid currentColor; } .foo:hover { color: green; } .foo span { color: orange; cursor: pointer } .foo span:hover { color: currentColor; }
HTML paragraph text.
また、g 要素と color 属性(または color プロパティ)を使うとグループごとに共通の色を設定することができます。
文書構造 関連要素
SVG は XML なので階層構造をとり、データはツリー構造で表わすことができます。
<svg width="300px" height="200px" viewBox="0 0 300 200"> <g stroke="green" stroke-width="3" fill="lightgreen" fill-opacity="0.5"> <circle cx="50" cy="60" r="40"/> <rect x="70" y="50" width="100" height="60"/> </g> </svg>
svg └── g ├── circle └── rect
詳細:SVG 1.1 仕様 (第2版)5 文書構造 日本語訳
SVG 文書片という用語が使われますが、これは「SVG document fragment」を訳したもので(fragment は断片)、svg 要素で始まる XML ドキュメントサブツリーを意味し、大雑把に言うと、SVG 文書片とは svg 要素をトップレベルとした要素ツリーを指します。
文書構造に関わる主な要素には以下のようなものがあります。
- svg 要素:SVG(文書片)を定義する要素
- desc 要素:画像の説明を記述する要素
- title 要素:画像の短い説明(タイトル)を記述する要素
- g 要素:グループ化を行う要素
- defs 要素:SVG を構成する部品を再利用できるように定義する要素
- use 要素: defs 要素で定義した要素を参照する要素
- a 要素:ハイパーリンクを表す要素
desc 要素と title 要素
desc 要素や title 要素を使って画像(グラフィックス要素)の説明を記述することができます。
desc 要素と title 要素はグラフィックの一部としては出力されません(グラフィックスのレンダリングには影響を及ぼしません)。
要素 | 説明 |
---|---|
desc 要素 | グラフィックスの説明に使います。title 要素と一緒に使うことができます。 |
title 要素 | グラフィックスのタイトルや短い説明に使います。desc 要素と一緒に使うことができます。ツールチップとして表示されます。 |
title 要素は、親要素の「最初の子要素」として記述します。
<svg width="100" height="100" viewBox="0 0 100 100"> <title>正方形描画サンプル</title> <desc>rect 要素を使った幅と高さ 80 でストロークが 5 の正方形のサンプル</desc> <rect x="10" y="10" width="80" height="80" fill="gold" stroke="silver" stroke-width="5"/> </svg>
SVG アクセシビリティ
SVG の title 要素や desc 要素はほとんどのスクリーンリーダーでの読み上げに対応していないようです。
そのため、SVG の title 要素や desc 要素の内容をスクリーンリーダーで読み上げられるようにするには、WAI-ARIA を使います。
- desc 要素や title 要素に id 属性を付与して aria-labelledby に id 属性の値を指定
- 適切な role 属性(role="img" など)を指定
以下は前述の例に、aria-labelledby 及び role 属性を追加した例です。
<svg viewBox="0 0 100 100" role="img" aria-labelledby="foo bar" > <title id="foo">正方形描画サンプル</title> <desc id="bar">rect 要素を使った幅と高さ 80 でストロークが 5 の正方形のサンプル</desc> <rect x="10" y="10" width="80" height="80" fill="gold"/> </svg>
g 要素(グループ化)
g 要素はグラフィックス要素(描画される要素)をグループ化するための要素です。
g 要素は階層構造をとることができ、他の g 要素を任意の階層にわたって入れ子にすることができます。
複数のグラフィックス要素をグループ化することで、それらのスタイルを一括で設定したりすることでできます。g 要素に適用された変形はその全ての子要素に対して実行されます。
この要素に専用属性はありません。MDN SVG 要素リファレンス g
以下は circle と rect 要素をグループ化してスタイルを設定する例です。
<svg width="300px" height="200px" viewBox="0 0 300 200"> <g stroke="green" stroke-width="3" fill="lightgreen" fill-opacity="0.5"> <circle cx="50" cy="60" r="40"/> <rect x="70" y="50" width="100" height="60"/> </g> </svg>
要素に直接プレゼンテーション属性や style 属性が設定されている場合はそちらの値が優先されます。
<svg width="300px" height="200px" viewBox="0 0 300 200"> <g stroke="green" stroke-width="3" fill="lightgreen" fill-opacity="0.5"> <circle cx="50" cy="60" r="40" fill="orange"/> <rect x="70" y="50" width="100" height="60"/> </g> </svg>
値が設定されていない場合は、その要素の最も近い g 要素の設定値が適用されます。
以下の場合、2番目の circle 要素は直近の g 要素の stroke や fill などの値が適用されます。
<svg width="300px" height="200px" viewBox="0 0 300 200"> <g stroke="green" stroke-width="3" fill="lightgreen" fill-opacity="0.5"> <circle cx="50" cy="60" r="40" fill="orange"/> <rect x="70" y="50" width="100" height="60"/> <g stroke="red" stroke-width="1" style="fill:yellow" fill-opacity="0.5"> <circle cx="90" cy="90" r="50"/> <rect x="150" y="30" width="60" height="60" fill="blue"/> </g> </g> </svg>
g 要素と color 属性
g 要素に color 属性または CSS で color プロパティに色を設定して、グループ化された g 要素の子要素で currentColor キーワードを使って設定した色を参照することができます。
<svg width="300px" height="200px" viewBox="0 0 300 200"> <g color="green"> <circle cx="50" cy="60" r="40" fill="currentColor"/> <rect x="100" y="30" width="100" height="60" stroke="currentColor" stroke-width="10"/> </g> </svg>
以下は g 要素に CSS で color プロパティを設定する場合の例です(結果は上記と同じです)。
<svg width="300px" height="200px" viewBox="0 0 300 200"> <g style="color:green"> <circle cx="50" cy="60" r="40" fill="currentColor"/> <rect x="100" y="30" width="100" height="60" stroke="currentColor" stroke-width="10"/> </g> </svg>
g 要素 と color 属性(または color プロパティ)を使うとグループごとに共通の色を簡単に設定(管理)することができます。g 要素に指定している色を変えれば配下の要素の色を変えることができます。
<svg width="300px" height="300px" viewBox="0 0 300 300"> <g color="green"> <text x="20" y="20" fill="currentColor">Green Group</text> <circle cx="50" cy="80" r="40" stroke="currentColor" stroke-width="10" stroke-opacity="0.5" fill="currentColor"/> <rect x="110" y="40" width="100" height="60" stroke="currentColor" stroke-width="10" fill="currentColor" fill-opacity="0.5"/> <line x1="0" y1="115" x2="240" y2="115" stroke="currentColor" stroke-width="5"/> </g> <g style="color:orange"> <text x="20" y="160" fill="currentColor">Orange Group</text> <circle cx="50" cy="220" r="40" stroke="currentColor" stroke-width="10" stroke-opacity="0.5" fill="currentColor"/> <rect x="110" y="180" width="100" height="60" stroke="currentColor" stroke-width="10" fill="currentColor" fill-opacity="0.5"/> <line x1="0" y1="255" x2="240" y2="255" stroke="currentColor" stroke-width="5"/> </g> </svg>
defs 要素(再利用可能な部品の定義)
defs 要素には後で利用するための図形要素やグラデーションなどを定義しておくことができ、必要な場所で use 要素などで参照して利用することができます。図形のひな形の定義には symbol 要素も使えます。
SVG の可読性や操作性の向上の観点から参照される可能性のある要素は defs 要素内に定義することが推奨されています。ページ全体で有効になる style 要素を使ったスタイルの設定なども記述できます。
defs 要素内の要素は直接描画されることはありません。それらの要素を描画するには描画したい場所で use 要素などを使用して参照します。※ use 要素は defs 要素外の要素にも使えます。
defs 要素を使って定義だけをまとめておくことができますが、svg 要素を記述するとスペースを取るのでそのような場合は display: none や width と height を0に設定する等で非表示にすることができます。
この要素に専用属性はありません。MDN SVG 要素リファレンス defs
以下は defs 要素に半径 50、ストロークの太さが 5、フィルの不透明度が 0.5 の円(circle)を定義し、circle1 という ID を付与して、use 要素の href 属性(xlink:href 属性)に定義した円の ID を指定して表示する例です。
※ defs 要素内に定義する要素の ID は HTML 文書の中で一意となるようにする必要があります。
<svg width="240px" height="200px" viewBox="0 0 240 200"> <defs> <circle id="circle1" r="50" stroke-width="5" fill-opacity="0.5"/> </defs> <use href="#circle1" x="60" y="60" fill="gold" stroke="gold" /> <use href="#circle1" x="100" y="100" stroke="pink" fill="pink"/> <use href="#circle1" x="140" y="60" fill="lightblue" stroke="lightblue" /> </svg>
定義した円は同じページであれば以下のように別の svg 要素内からでも参照できます。
<svg width="240px" height="200px" viewBox="0 0 240 200"> <use href="#circle1" x="60" y="100" fill="gold" stroke="gold" /> <use href="#circle1" x="100" y="60" stroke="pink" fill="pink"/> <use href="#circle1" x="140" y="100" fill="lightblue" stroke="lightblue" /> </svg>
以下は defs 要素に text 要素でテキストを定義して use 要素で利用する例です。
<svg width="240px" height="60px" viewBox="0 0 240 60"> <defs> <text id="text1" x="0" y="10">Text</text> </defs> <use href="#text1" x="0" y="20" fill="blue" font-size="30"/> <use href="#text1" x="0" y="50" fill="pink" font-size="24"/> </svg>
以下は linearGradient 要素を defs 要素内に定義して ID を付与し、長方形(rect)の fill プロパティに定義した線型グラデーションへの参照を指定して長方形の塗りをグラデーションにする例です。
※ defs 要素内に定義する要素の ID は HTML 文書の中で一意である必要があります。
<svg width="200px" height="100px" viewBox="0 0 200 100"> <defs> <linearGradient id="gradient01"> <stop offset="10%" stop-color="green" /> <stop offset="90%" stop-color="orange" /> </linearGradient> </defs> <rect x="10" y="10" width="180" height="80" fill="url(#gradient01)" /> </svg>
svg 要素を非表示にする
svg 要素はその内容がなくても記述すると一定のスペースを取ってしまいます。
<svg style="background-color:darkseagreen;"></svg>
上記の svg 要素は内容は何もありませんが、HTML の中に記述すると以下のように幅と高さがあります(わかりやすいように背景色を指定しています)。
そのため、defs や symbol、clipPath、mask 要素など(要素自体は非表示)を使って定義のみをする場合は、例えば以下のように width height を0、position:absolute にして非表示にすることができます。
以下はインラインで指定する例です。
<svg width="0" height="0" style="position:absolute;"> ... </svg>
svg 要素にクラス属性を付与して別途スタイルシートで指定することもできます。
.svg-defs { position:absolute; width: 0; height: 0; }
use 要素
use 要素は他の要素を参照してそのグラフィック内容を取り込んで指定した位置に描画(複製)します。
基本図形要素やテキスト要素、svg、symbol、g、use 要素が再利用(インスタンス化)の対象になり参照できます。但し、use 要素自身の親要素を参照することはできません。
属性 | 意味 |
---|---|
href | 複製(参照)する要素やフラグメントへの URL(ID 等) |
xlink:href | 複製(参照)する要素やフラグメントの IRI 参照(SVG 2 では非推奨 ※) |
x | この要素の X 座標(複製する要素の位置の X 座標) |
y | この要素の Y 座標(複製する要素の位置の Y 座標) |
width | この要素の幅。use が svg または symbol 要素を参照している場合のみ有効。 |
height | この要素の高さ。use が svg または symbol 要素を参照している場合のみ有効。 |
※ SVG 2 で xlink:href 属性が非推奨になり、href に置き換えられました。但し、 xlink:href はブラウザー間の互換性のために今でも実装されているようです。
use のほとんどの属性は、use から参照される要素に指定されている属性を上書きしません。
use 要素に指定した x、 y、 width、 height、 href の各属性のみが参照される要素に設定されているものを上書きします(width と height は svg または symbol 要素を参照している場合のみ有効)。
但し、参照される要素に設定されていない他のすべての属性は、 use 要素に指定された値が適用されます。
以下の場合、1つ目の rect 要素を参照している use 要素に指定した x と y 属性は上書きされていますが、width と height は効果がありません。その他の fill、stroke、stroke-width、fill-opacity は元の要素に設定されていないので指定された値が適用されています。
2つ目の rect 要素を参照している use 要素の fill、stroke、stroke-width、fill-opacity 属性は元の要素にすでに設定されているので適用されません(上書きできません)。
svg 要素のボーダー及び水色のガイドラインと座標のテキストの描画は省略しています。
<svg id="my_svg1" width="240px" height="120px" viewBox="0 0 240 120"> <defs> <rect id="rect1" x="10" y="10" width="100" height="60"/> <rect id="rect2" x="10" y="10" width="100" height="60" fill="gold" stroke="silver" stroke-width="10" fill-opacity="0.5"/> </defs> <use href="#rect1" x="5" y="5" width="80" height="80" fill="lightgreen" stroke="green" stroke-width="5"/> <use href="#rect2" x="80" y="30" fill="pink" stroke="purple" stroke-width="5" fill-opacity="1"/> </svg>
以下は前述の id が my_svg1 の svg 要素を use 要素で複製しています。この場合、指定した width と height は有効で、上書きされます。
<svg width="240px" height="120px" viewBox="0 0 240 120"> <use href="#my_svg1" x="0" y="0" width="120" height="60"/> <use href="#my_svg1" x="120" y="0" width="120" height="60"/> <use href="#my_svg1" x="60" y="60" width="120" height="60"/> </svg>
use 要素の描画の基準
use 要素に設定した x 属性 と y 属性は図形を複製する際の基準点となります。そして複製された図形はこの点を原点として描画されます。以下の場合、複製された正方形は (30,30) を原点として描画されます。
use 要素に x="0" y="0" を設定すると、元の画像に重なります。
<svg width="240px" height="200px" viewBox="0 0 240 200"> <rect id="rect3" x="30" y="30" width="100" height="100" fill="purple" fill-opacity="0.3"/> <use href="#rect3" x="30" y="30" stroke="purple" stroke-width="10"/> <!-- 以下はピンクのガイドライン(line 要素)と座標のテキスト(text 要素) --> <line x1="30" y1="0" x2="30" y2="200" stroke="pink" stroke-width="1" stroke-dasharray="3"/> <line x1="60" y1="0" x2="60" y2="200" stroke="pink" stroke-width="1" stroke-dasharray="3"/> <line x1="0" y1="30" x2="240" y2="30" stroke="pink" stroke-width="1" stroke-dasharray="3"/> <line x1="0" y1="60" x2="240" y2="60" stroke="pink" stroke-width="1" stroke-dasharray="3"/> <text x="10" y="26" fill="mediumpurple">30,30</text> <text x="38" y="52" fill="purple">60,60</text> </svg>
以下は楕円の図形を use で同じ座標に複製して transform 属性の rotate を使って回転させています。
<div style="max-width:200px;background-color:#E9FAD0; border:1px solid #C3D0AF"> <svg viewBox="0 0 240 240"> <ellipse id="ellipse1" cx="120" cy="120" rx="100" ry="20" stroke="cadetblue" stroke-width="1" fill="darkcyan" fill-opacity="0.2"/> <use href="#ellipse1" x="0" y="0" transform="rotate(30,120,120)"/> <use href="#ellipse1" x="0" y="0" transform="rotate(60,120,120)"/> <use href="#ellipse1" x="0" y="0" transform="rotate(90,120,120)"/> <use href="#ellipse1" x="0" y="0" transform="rotate(120,120,120)"/> <use href="#ellipse1" x="0" y="0" transform="rotate(150,120,120)"/> </svg> </div>
以下は上記同様、楕円の図形を use で複製していますが、fill 属性をそれぞれの複製した要素で変更するため、元の画像は defs に定義して fill を指定していません。最初の use 要素での複製は元の画像(表示はされていない)に重なっていて、前述の例より use 要素の数は1つ多くなっています。
<div style="max-width:200px; border:1px solid #ddd"> <svg viewBox="0 0 240 240"> <defs> <ellipse id="ellipse2" cx="120" cy="120" rx="100" ry="20" fill-opacity="0.3"/> </defs> <use href="#ellipse2" x="0" y="0" fill="gray"/> <use href="#ellipse2" x="0" y="0" transform="rotate(30,120,120)" fill="green"/> <use href="#ellipse2" x="0" y="0" transform="rotate(60,120,120)" fill="blue"/> <use href="#ellipse2" x="0" y="0" transform="rotate(90,120,120)" fill="purple"/> <use href="#ellipse2" x="0" y="0" transform="rotate(120,120,120)" fill="red"/> <use href="#ellipse2" x="0" y="0" transform="rotate(150,120,120)" fill="orange"/> </svg> </div>
外部 SVG ファイル
同じ HTML ファイル内の要素だけではなく、use 要素を使って外部の svg ファイルの要素を参照することもできます。
以下はフリー素材サイトからダウンロードした SVG ファイルです。
元のファイルの不要なコメントや属性は削除しておきます。また、use 要素で塗りなどを指定するため、元のファイルのスタイルや fill などのプレゼンテーション属性も削除します。
<!--?xml version="1.0" encoding="utf-8"?--> <!-- Generator: Adobe Illustrator 18.1 --> <svg version="1.1" id="37" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="width: 256px; height: 256px; opacity: 1;" xml:space="preserve"> <style type="text/css"> .st0{fill:#4B4B4B;} </style> <g> <path class="st0" d="M106.003,348.768c12・・・中略・・・ C104.455,348.768z" style="fill: rgb(75, 75, 75);"></path> <path class="st0" d="M439.482,93.253C287・・・中略・・・,C373.177,345.279z" style="fill: rgb(75, 75, 75);"></path> </g> </svg>
以下は上記ファイルの不要な部分を削除したものです(SVGOMG を使って最適化もしています)。
use 要素で指定できるように図形に id を付与します。
この例の場合、図形は2つの path 要素を g 要素でグループ化してあるので、g 要素に id 属性を追加します。また、path 要素にも id 属性を指定して個別に利用できるようにしています。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <g id="leaf"> <path id="part1" d="M106.003 348.768c12.848-115.627 86.282-211.197 185.781-257.238C268.378 53.37 236.62 22.365 199.921 0 62.447 65.536-2.416 227.413 54.819 370.914c14.055 35.265 34.373 66.122 58.994 92.125a321.83 321.83 0 01-7.81-114.271z"></path> <path id="part2" d="M439.482 93.253C287.34 86.361 153.924 198.646 136.859 352.197c-6.209 55.924 3.883 109.888 26.406 157.215 2.134.289 4.225.63 6.35.866 152.43 16.933 289.722-92.903 306.654-245.325 6.901-62.117-7.259-121.723-36.787-171.7zm-148.53 252.026c-48.56 75.218-93.716 132.454-100.854 127.853-7.119-4.609 26.484-69.305 75.078-144.515 48.577-75.218 93.734-132.455 100.862-127.854 7.139 4.61-26.482 69.306-75.086 144.516z"></path> </g> </svg>
以下の例では、参照する側の svg 要素の viewBox 属性は元のファイルにあわせ、width と height で表示サイズを指定しています。
use 要素では href 属性で SVG ファイルの図形部分を指定します。
<svg width="100px" height="100px" viewBox="0 0 512 512"> <use href="../images/svg/leaf.svg#leaf" x="0" y="0" fill="lightgreen"/> </svg>
以下はストロークを追加する例です。ストロークの部分が表示領域の外にならないように viewBox の値を調整しています。
<svg width="100px" height="100px" viewBox="0 0 522 522"> <use href="../images/svg/leaf.svg#leaf" x="0" y="0" fill="lightblue" stroke="pink" stroke-width="10"/> </svg>
以下は個別に id を指定した path 要素を use 要素で複製する例です。それぞれの use 要素で x, y 属性で位置を調整しています。また、幅が広くなるので viewBox の値を調整しています。
<svg width="200px" height="100px" viewBox="0 0 1024 512"> <use href="../images/svg/leaf.svg#part1" x="0" y="0" fill="green" fill-opacity="0.7"/> <use href="../images/svg/leaf.svg#part2" x="0" y="0" fill="orange" fill-opacity="0.7"/> <use href="../images/svg/leaf.svg#part2" x="256" y="-50" fill="purple" fill-opacity="0.5" stroke="pink" stroke-width="10"/> <use href="../images/svg/leaf.svg#part2" x="512" y="0" fill="gold" fill-opacity="0.5" transform="rotate(30,740,300)"/> </svg>
symbol 要素
symbol 要素は図形などのひな形(テンプレートオブジェクト)を定義するために使用し、use 要素を使ってインスタンス化することで図形を描画します。
symbol 要素を使うと複数の図形を一つの図形として扱うことができます。g 要素も複数の画像をグループ化することができますが、symbol 要素はそれ自体としては描画されません(図形を定義するための要素)。
また、symbol 要素は viewBox 属性と preserveAspectRatio 属性を指定でき、独自の座標系を定義することができます。
更に、use 要素で width と height の指定が有効で、表示内容を簡単に拡大・縮小することができます。
symbol 要素には以下のような属性を指定できます。
属性 | 意味 |
---|---|
width | symbol 要素の幅(初期値:auto) |
height | symbol 要素の高さ(初期値:auto) |
viewBox | 描画する図形の座標系を定義する属性(初期値:なし) |
preserveAspectRatio | 図形の表示サイズと viewBox の大きさとでアスペクト比が異なっている場合の画像の変形方法を指定(初期値:xMidYMid meet) |
x | symbol 要素の X 座標(初期値:0) |
y | symbol 要素の Y 座標(初期値:0) |
以下は symbol 要素に1つの rect 要素と3つの circle 要素で定義した図形を use 要素で描画する例です。以下の例では use 要素に属性を指定していないのでデフォルトの初期値が適用されます。
<svg width="300px" height="200px" viewBox="0 0 300 200"> <symbol id="symbol1" viewBox="0 0 300 200"> <rect x="0" y="0" width="300" height="200" fill="gold"/> <circle cx="100" cy="100" r="50" fill="lightgreen"/> <circle cx="150" cy="100" r="50" fill="lightblue"/> <circle cx="200" cy="100" r="50" fill="lightpink"/> </symbol> <use href="#symbol1"/> </svg>
以下は前述で定義した symbol 要素をデフォルトの大きさと、幅と高さを半分のサイズに指定した図形を表示する例です。
g 要素には width や height を指定しても無視されますが、symbol 要素には適用されます。
<svg width="300px" height="200px" viewBox="0 0 300 200"> <use href="#symbol1"/> <use href="#symbol1" width="150" height="100" x="50" y="0" fill-opacity="0.8"/> </svg>
symbol 要素は別途定義してある symbol 要素を使って新たに定義することもできます。以下は前述で定義した symbol 要素を使って別の symbol 要素を定義する例です。
<svg width="240px" height="1600px" viewBox="0 0 240 160"> <!-- #symbol1 を利用して #symbol 2 を定義 --> <symbol id="symbol2" viewBox="0 0 300 200"> <use href="#symbol1"/> <use href="#symbol1" width="150" height="100" x="80" y="0" fill-opacity="0.8"/> </symbol> <use href="#symbol2" width="240" height="160"/> </svg>
SVG アイコンを表示
以下は Bootstrap のアイコンの path の部分を symbol 要素に定義して、use 要素で表示する例です。
以下は Bootstrap のアイコン card-image.svg をダウンロード(コピー)したものです。
このまま HTML に記述すれば、fill に currentColor が指定されているので親要素の色で 16 x 16 ピクセルのアイコンが表示されますが、複数回表示する場合、毎回このコードを記述するのは大変です。
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-card-image" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M14.5 3h-13a.5.5 0 0 0-.5.5v9c0 .013 0 .027.002.04V12l2.646-2.354a.5.5 0 0 1 .63-.062l2.66 1.773 3.71-3.71a.5.5 0 0 1 .577-.094L15 9.499V3.5a.5.5 0 0 0-.5-.5zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13zm4.502 3.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/> </svg>
以下のように上記コードの path の部分を svg 要素の symbol 要素内に記述しておけば、use 要素を使ってアイコンを表示することができます。
以下のコードは表示するページの HTML の body 内に記述します。symbol 要素自体は非表示ですが、svg 要素がスペースを取るので display: none で非表示にしておきます。
<svg style="display: none"> <symbol id="symbol-image" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M14.5 3h-13a.5.5 0 0 0-.5.5v9c0 .013 0 .027.002.04V12l2.646-2.354a.5.5 0 0 1 .63-.062l2.66 1.773 3.71-3.71a.5.5 0 0 1 .577-.094L15 9.499V3.5a.5.5 0 0 0-.5-.5zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13zm4.502 3.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/> </symbol> </svg>
アイコンを表示する場所で svg 要素に width と height、viewBox を適宜指定し、use 要素でアイコンを描画します。
<svg width="320" height="100" viewBox="0 0 320 100"> <use href="#symbol-image" x="0" y="0" width="30" height="30" fill="green"/> <use href="#symbol-image" x="50" y="0" width="50" height="50" fill="orange"/> <use href="#symbol-image" x="120" y="0" width="70" height="70" fill="mediumpurple"/> <use href="#symbol-image" x="220" y="0" width="90" height="90" fill="lightblue"/> </svg>
以下も Bootstrap Icons を利用した例です。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 600" style="max-width: 640px;"> <defs> <!-- 矢印のマーカーの定義 --> <marker id="arrow1x" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" fill="#666" orient="auto"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> <marker id="arrow2x" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" fill="#666" orient="auto-start-reverse"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> </defs> <!-- SVG アイコンを symbol で定義(width と height で大きさを指定)して id を指定 --> <symbol id="file" width="40" height="40" viewBox="0 0 16 16"> <path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z" /> </symbol> <symbol id="folder" width="34" height="34" viewBox="0 0 16 16"> <path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z" /> </symbol> <symbol id="database" width="40" height="40" viewBox="0 0 16 16"> <path d="M4.318 2.687C5.234 2.271 6.536 2 8 2s2.766.27 3.682.687C12.644 3.125 13 3.627 13 4c0 .374-.356.875-1.318 1.313C10.766 5.729 9.464 6 8 6s-2.766-.27-3.682-.687C3.356 4.875 3 4.373 3 4c0-.374.356-.875 1.318-1.313ZM13 5.698V7c0 .374-.356.875-1.318 1.313C10.766 8.729 9.464 9 8 9s-2.766-.27-3.682-.687C3.356 7.875 3 7.373 3 7V5.698c.271.202.58.378.904.525C4.978 6.711 6.427 7 8 7s3.022-.289 4.096-.777A4.92 4.92 0 0 0 13 5.698ZM14 4c0-1.007-.875-1.755-1.904-2.223C11.022 1.289 9.573 1 8 1s-3.022.289-4.096.777C2.875 2.245 2 2.993 2 4v9c0 1.007.875 1.755 1.904 2.223C4.978 15.71 6.427 16 8 16s3.022-.289 4.096-.777C13.125 14.755 14 14.007 14 13V4Zm-1 4.698V10c0 .374-.356.875-1.318 1.313C10.766 11.729 9.464 12 8 12s-2.766-.27-3.682-.687C3.356 10.875 3 10.373 3 10V8.698c.271.202.58.378.904.525C4.978 9.71 6.427 10 8 10s3.022-.289 4.096-.777A4.92 4.92 0 0 0 13 8.698Zm0 3V13c0 .374-.356.875-1.318 1.313C10.766 14.729 9.464 15 8 15s-2.766-.27-3.682-.687C3.356 13.875 3 13.373 3 13v-1.302c.271.202.58.378.904.525C4.978 12.71 6.427 13 8 13s3.022-.289 4.096-.777c.324-.147.633-.323.904-.525Z" /> </symbol> <symbol id="pc" width="32" height="32" viewBox="0 0 16 16"> <path d="M1.5 0A1.5 1.5 0 0 0 0 1.5v7A1.5 1.5 0 0 0 1.5 10H6v1H1a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-5v-1h4.5A1.5 1.5 0 0 0 16 8.5v-7A1.5 1.5 0 0 0 14.5 0h-13Zm0 1h13a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .5-.5ZM12 12.5a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Zm2 0a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0ZM1.5 12h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1 0-1ZM1 14.25a.25.25 0 0 1 .25-.25h5.5a.25.25 0 1 1 0 .5h-5.5a.25.25 0 0 1-.25-.25Z" /> </symbol> <symbol id="server" width="32" height="32" viewBox="0 0 16 16"> <path d="M5 0a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1H5Zm.5 14a.5.5 0 1 1 0 1 .5.5 0 0 1 0-1Zm2 0a.5.5 0 1 1 0 1 .5.5 0 0 1 0-1ZM5 1.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5ZM5.5 3h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1 0-1Z" /> </symbol> <!-- 上記で定義した symbol と基本図形要素などを使って symbol を定義 --> <symbol id="user" width="400" height="500" viewBox="0 0 400 500"> <text x="40" y="40" font-size="14" fill="#999">ユーザーのPC</text> <rect x="0" y="50" width="320" height="320" stroke="#999" stroke-width="1" fill="none" rx="6" /> <!-- PCのアイコンの後ろに線が見えないように白で塗りつぶした長方形を配置 --> <rect x="0" y="30" width="32" height="32" stroke-width="0" fill="white" /> <use href="#pc" x="0" y="30" fill="#999" /> <rect x="30" y="100" width="260" height="240" stroke="#db7b05" stroke-width="1" fill="none" rx="10" /> <rect x="20" y="80" width="32" height="30" stroke-width="0" fill="white" /> <use href="#folder" x="20" y="80" fill="#db7b05" /> <text x="60" y="90" font-size="14" fill="#db7b05">プロジェクト(作業ディレクトリ)</text> <use href="#database" x="140" y="135" fill="#166d24" /> <text x="100" y="130" font-size="14" fill="#166d24">ローカルリポジトリ</text> <rect x="50" y="240" width="220" height="80" stroke="#3e579c" stroke-width="1" fill="none" rx="6" /> <text x="165" y="210" font-size="14" fill="#999">commit などの操作</text> <polyline points="160,220 160,190" fill="none" stroke="#666" stroke-width="1.5" marker-end="url(#arrow2x)" marker-start="url(#arrow2x)" /> <text x="65" y="260" font-size="14" fill="#3e579c">変更履歴の管理対象のファイル</text> <use href="#file" x="80" y="270" fill="#3e579c" /> <use href="#file" x="130" y="270" fill="#3e579c" /> <use href="#file" x="180" y="270" fill="#3e579c" /> </symbol> <symbol id="remote" width="800" height="200" viewBox="0 0 800 200"> <rect x="240" y="20" width="240" height="100" stroke="#999" stroke-width="1" fill="none" rx="6" /> <rect x="0" y="30" width="32" height="32" stroke-width="0" fill="white" /> <use href="#server" x="240" y="0" fill="#999" /> <text x="270" y="15" font-size="14" fill="#999">サーバー</text> <text x="300" y="50" font-size="14" fill="#166d24">リモートリポジトリ</text> <use href="#database" x="340" y="60" fill="#166d24" /> </symbol> <!-- 定義した symbol と基本図形要素などを使って描画 --> <use href="#remote" x="0" y="0" /> <polyline points="200,220 270,150" fill="none" stroke="#666" stroke-width="1.5" marker-end="url(#arrow1x)" /> <polyline points="300,150 230,220" fill="none" stroke="#666" stroke-width="1.5" marker-end="url(#arrow1x)" /> <text x="190" y="190" font-size="14" fill="#999">Push</text> <text x="280" y="190" font-size="14" fill="#999">Pull</text> <use href="#user" x="0" y="210" /> <polyline points="500,220 430,150" fill="none" stroke="#666" stroke-width="1.5" marker-end="url(#arrow1x)" /> <polyline points="460,150 530,220" fill="none" stroke="#666" stroke-width="1.5" marker-end="url(#arrow1x)" /> <text x="420" y="190" font-size="14" fill="#999">Push</text> <text x="510" y="190" font-size="14" fill="#999">Pull</text> <use href="#user" x="400" y="210" /> </svg>
a 要素
SVG では、図形に対して HTML などと同じハイパーリンクを設定する SVG の a 要素があります(HTML の a 要素と同じ名前ですが、別の要素です)。
HTML の a 要素と良く似ていますが、テキストを囲むものだけでなく、図形を囲むリンクを生成することができます。
以下は a 要素の属性の一部です。
属性 | 意味 |
---|---|
href | リンク先の URL または URL フラグメント。 |
xlink:href | リンク先の URL または URL フラグメント。古いブラウザー向け(SVG2 非推奨) |
target | リンクされた URL の表示先(_self _parent _top _blank) |
以下は text 要素で作成したテキストにリンクを指定した例です。リンクの色を指定するには fill を使用することができます。
<svg width="150" height="50" viewBox="0 0 150 30"> <text x="0" y="20"><a href="#a_elem" fill="blue">a 要素でハイパーリンク</a></text> </svg>
SVG ではリンクに既定のスタイルがないので、CSS や SVG の style 要素などを使ってスタイルを設定することができます(CDATA ブロックは省略可能)。
<svg width="100px" height="30px" viewBox="0 0 100 30"> <style type="text/css"><![CDATA[ .mylink a { fill: #3987C7; text-decoration: underline; } .mylink a:hover { fill: pink; } ]]></style> <text x="0" y="20" class="mylink"><a href="#a_elem">リンク</a></text> </svg>
以下は path で描画した三角形の図形にリンクを指定した例です。
HTML の a 要素ではリンクの範囲は四角形になりますが、SVG ではリンクの範囲は図形の形状と同じになります。
但し、fill 属性に none を指定すると塗りの部分はリンクの範囲に含まれません。2つ目の三角形はストロークの部分のみがリンクの対象範囲となっています。
<svg width="240" height="100" viewBox="0 0 240 100"> <a href="#a_elem"> <path d="M10 80 L60 10 L110 80 H10z" stroke="mediumpurple" stroke-width="5" fill="pink"/> </a> <a href="#a_elem"> <path d="M130 80 L180 10 L230 80 H130z" stroke="mediumpurple" stroke-width="5" fill="none"/> </a> </svg>
以下のように hover 時に fill に none 以外(transparent を含む)を指定すれば、クリックできるようにはなります。
※以下の方法でスタイルを指定すると、ページ全体に適用されます。また style 要素は defs 要素で囲まなくても問題ありません(SVG の style 要素)。
<svg width="240" height="100" viewBox="0 0 240 100"> <defs> <style type="text/css"> a.svg_link path:hover { fill: purple; } </style> </defs> <a class="svg_link" href="#a_elem"> <path d="M10 80 L60 10 L110 80 H10z" stroke="mediumpurple" stroke-width="5" fill="pink"/> </a> <a class="svg_link" href="#a_elem"> <path d="M130 80 L180 10 L230 80 H130z" stroke="mediumpurple" stroke-width="5" fill="none"/> </a> </svg>
以下は rect 要素でボタンを描画して text 要素でラベルを表示する例です。
text 要素には下にある rect 要素にイベントを伝えるため pointer-events="none" という属性を指定しています。この指定がないと、ラベル部分がリンクの範囲の対象とはならないためリンクが機能しません(文字部分をクリックできません)。関連:pointer-events
<svg width="150" height="60" viewBox="0 0 150 60"> <defs> <style type="text/css"> a.svg_link rect:hover { fill: indigo; } </style> </defs> <a class="svg_link" href="#a_elem"> <rect x="10" y="10" width="120" height="40" rx="20" ry="20" fill="#BFC8F7" stroke="#537394" stroke-width="4"/> </a> <text x="30" y="42" pointer-events="none" font-size="30" fill="yellow">Click</text> </svg>
image 要素
image 要素を使うと JPEG や PNG やなどのラスター画像や MIME タイプ "image/svg+xml" の SVG ファイルを参照して矩形の領域に描画することができます。
<svg width="200" height="113" viewBox="0 0 200 113"> <image href="../images/sample.jpg" width="200" height="113"/> </svg>
title 要素を含めることもできます。
<svg width="200" height="113" viewBox="0 0 200 113"> <image href="../images/jquery/sample06.jpg" width="200" height="113" aria-labelledby="sunset_title"> <title id="sunset_title">海に沈む夕日</title> </image> </svg>
以下のような属性を指定できます。
HTML の img 要素とは異なり、width 属性と height 属性は必須になっています(SVG2 では省略可能になっています)。また img 要素では画像の URL は src 属性で指定しますが、image 要素の場合は href または xlink:href 属性で指定します。
属性 | 意味 |
---|---|
width | 描画される画像の幅(必須 ※SVG2 では省略可能) |
height | 描画される画像の高さ(必須 ※SVG2 では省略可能) |
x | 左上の X 座標(原点からの水平位置)。初期値は0 |
y | 左上の Y 座標(原点からの垂直位置)。初期値は0 |
href または xlink:href | 参照する画像ファイルの URL |
preserveAspectRatio | 画像の拡大縮小方法 |
use 要素で複製
use 要素を使って image 要素をコピーすることができます。
<svg width="300" height="220" viewBox="0 0 300 220" style="border: 1px solid #eee"> <image id="jpg1" href="../images/jquery/sample06.jpg" width="200" height="113"/> <text x="50" y="30" font-size="20" fill="gold">Sunset</text> <use href="#jpg1" x="30" y="50" opacity="0.8"/> <use href="#jpg1" x="60" y="75" opacity="0.6"/> <use href="#jpg1" x="90" y="100" opacity="0.4"/> </svg>
preserveAspectRatio
参照先の画像の image 要素による矩形の領域への配置や拡縮率は preserveAspectRatio 属性で指定することができます。
preserveAspectRatio 属性の評価時に利用される viewBox 属性の値は、参照先の内容で定義されます。つまり image 要素は暗黙の 'viewBox' の値: '0, 0, 画像の幅, 画像の高さ' を持ちます。
以下は縦長の画像を横長(width="300" height="200")の image 要素に表示する場合に、preserveAspectRatio 属性の値によりどのように表示されるかを確認するサンプルです。
preserveAspectRatio 属性の初期値は xMidYMid meet です。
<svg width="300" height="200" viewBox="0 0 300 200">
<image id="svg_image" href="../images/sample.jpg" width="300" height="200" preserveAspectRatio="xMidYMid meet"/>
</svg>
preserveAspectRatio に指定する xMidYMid や xMinYMin などは位置を指定する値で、meet や slice キーワードには以下のような意味があります。
- none: 均一なスケーリングを強制しない
- meet: 縦横比を保ち内部にフィットさせる(デフォルト)
- slice: 縦横比を保ち領域いっぱいに広げる(トリムされる)
preserveAspectRatio 属性の詳細は以下で確認できます。
マーカー
マーカーを使うと path や line、polyline、polygon 要素にマーカーを描画できます。
マーカーは marker 要素使って定義します(marker 要素自体は直接描画されることはありません)。
そしてマーカーを表示する要素で marker-start や marker-end、marker-mid などのマーカープロパティ(属性)を指定して、定義したマーカーを描画します。
<svg width="160px" height="160px" viewBox="0 0 110 110"> <defs> <!-- 矢印(三角)のマーカーの定義 --> <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> <!-- ドット(丸)のマーカーの定義 --> <marker id="dot" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="5" markerHeight="5"> <circle cx="5" cy="5" r="5" fill="red" /> </marker> </defs> <!-- L字型のライン(Y と X 軸)でマーカープロパティを指定して矢印を表示 --> <polyline points="10,10 10,100 100,100" fill="none" stroke="black" marker-start="url(#arrow)" marker-end="url(#arrow)" /> <!-- 折れ線でマーカープロパティを指定してドットを表示 --> <polyline points="20,90 29,45 47,60 63,30 80,40 99,15" fill="none" stroke="grey" marker-start="url(#dot)" marker-mid="url(#dot)" marker-end="url(#dot)" /> </svg>
マーカープロパティ
マーカーを描画(表示)するには、図形要素のマーカープロパティ(属性)で指定します。
属性 | 意味(値) |
---|---|
marker-start | 始点に描画されるマーカの URL を指定。初期値:none |
marker-mid | 始点と終点を除くすべての頂点に描画されるマーカの URL を指定。line 要素や始点と終点のみの場合は無効。初期値:none |
marker-end | 終点に描画されるマーカの URL を指定。初期値:none |
以下は marker 要素で定義したマーカーをマーカープロパティ(属性)で指定して描画する例です。
marker-mid は中間の頂点がない(始点と終点のみの)場合は無効で表示されないため、marker-mid を指定する図形(polyline)ではマーカーを描画する位置に頂点を追加しています。
<svg viewBox="0 0 160 80"> <defs> <!-- 右向き矢印(三角形)のマーカーの定義 --> <marker id="arrow1" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" fill="red"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> <!-- 左向き矢印のマーカーの定義 --> <marker id="arrow2" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" fill="blue"> <path d="M 0 5 L 10 0 L 10 10 z" /> </marker> <!-- ドット(丸)のマーカーの定義 --> <marker id="dot1" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="5" markerHeight="5"> <circle cx="5" cy="5" r="5" fill="orange" /> </marker> </defs> <!-- marker-end で右向き矢印のマーカーを終点に描画 --> <polyline points="10,10 100,10" fill="none" stroke="black" marker-end="url(#arrow1)"/> <!-- marker-start で左向き矢印のマーカーを始点に描画 --> <polyline points="10,30 100,30" fill="none" stroke="black" marker-start="url(#arrow2)"/> <!-- 中間に頂点を追加して marker-mid でマーカーを表示 --> <polyline points="10,50 50,50 100,50" fill="none" stroke="black" marker-mid="url(#arrow2)"/> <!-- 始点、中間の頂点、終点でマーカーを表示 --> <polyline points="10,70 45,70 70,70 100,70" fill="none" stroke="black" marker-start="url(#arrow2)" marker-mid="url(#dot1)" marker-end="url(#arrow1)"/> </svg>
marker 要素
マーカーの形状を定義する marker 要素には以下のような属性を指定できます。
viewBox、markerWidth、markerHeight 属性は svg 要素の viewBox、width、height 属性とほぼ同じで、マーカー図形の描画領域と表示領域(ビューポート)の幅と高さを定義します。
属性 | 意味 |
---|---|
viewBox | マーカーの描画領域(座標系)の定義。省略した場合は、左上隅を(0, 0)として markerWidth と markerHeight で指定された範囲。 |
markerWidth | マーカーの表示領域(ビューポート)の幅。初期値:初期値:3 |
markerHeight | マーカーの表示領域(ビューポート)の高さ。初期値:初期値:3 |
refX | (viewBox における)マーカーの基準となる点の X 座標。初期値:0 |
refY | (viewBox における)マーカーの基準となる点の Y 座標。初期値:0 |
orient | マーカーの角度。角度を数値で指定するか auto または auto-start-reverse を指定。初期値:0 |
markerUnits | マーカーサイズの基準。userSpaceOnUse(ユーザー座標系)または strokeWidth(ストロークの太さ)を指定。 初期値: strokeWidth |
preserveAspectRatio | 縦横比が異なる場合の拡大縮小方法。初期値:xMidYMid meet |
viewBox (描画領域と表示サイズ)
以下は同じ形状のマーカー(marker 要素)を viewBox 属性の指定をした場合と省略した場合の例です。
1つ目のマーカーは viewBox="0 0 10 10" を指定して、マーカーの描画領域を左上隅を(0, 0)として幅 10、高さ10 とし、その座標に polygon で頂点の座標(0,0 10,5 0,10)を定義しています。そしてその描画領域のサイズを幅 6(markerWidth)、高さ 6(markerHeight)で描画します。
2つ目のマーカーは viewBox を省略しているので viewBox="0 0 6 6"(0 0 markerWidth markerHeight)を指定したのと同じことになるため、polygon で頂点の座標(0,0 6,3 0,6)を定義しています。そしてその描画領域のサイズを幅 6(markerWidth)、高さ 6(markerHeight)で描画します。
<svg width="140px" height="100px" viewBox="0 0 140 100"> <!-- viewBox="0 0 10 10" --> <marker id="marker1" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6"> <polygon points="0,0 10,5 0,10" /> </marker> <!-- viewBox なし --> <marker id="marker2" refX="3" refY="3" markerWidth="6" markerHeight="6"> <polygon points="0,0 6,3 0,6" /> </marker> <line x1="20" y1="20" x2="120" y2="20" stroke="black" stroke-width="1" marker-end="url(#marker1)" /> <line x1="20" y1="60" x2="120" y2="60" stroke="black" stroke-width="1" marker-end="url(#marker2)" /> </svg>
上記で定義した2つのマーカーは同じ形状で描画されます。
以下は前述の1つ目のマーカー(id="marker1" の marker 要素)の例です。
- viewBox:描画領域
- markerWidth / markerHeight:表示サイズ
以下は viewBox と polygon の定義が同じ marker 要素ですが、markerWidth と markerHeight が異なるので描画されるマーカーのサイズが異る例です。
<svg width="140px" height="100px" viewBox="0 0 140 100"> <!-- markerWidth="6" markerHeight="6" --> <marker id="marker3" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6"> <polygon points="0,0 10,5 0,10" /> </marker> <!-- markerWidth="10" markerHeight="10" --> <marker id="marker4" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="10" markerHeight="10"> <polygon points="0,0 10,5 0,10" /> </marker> <line x1="20" y1="20" x2="120" y2="20" stroke="black" stroke-width="1" marker-end="url(#marker3)" /> <line x1="20" y1="60" x2="120" y2="60" stroke="black" stroke-width="1" marker-end="url(#marker4)" /> </svg>
orient(角度の指定・調整)
marker 要素の orient 属性を使うと、マーカーの角度(描画方向)を指定することができます。
auto を指定すると、線の方向に合わせてマーカーの回転量が自動的に調整されます。
auto-start-reverse を指定すると、始点と終点とでマーカー図形を180°反転します。
<svg viewBox="0 0 160 180"> <defs> <!-- 右向き矢印(orient="auto")のマーカーの定義 --> <marker id="arrow3" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" fill="blue" orient="auto"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> <!-- 右向き矢印(orient="auto-start-reverse")のマーカーの定義 --> <marker id="arrow4" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" fill="red" orient="auto-start-reverse"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> </defs> <!-- 左から右方向へ描画(orient="auto" のマーカー) --> <polyline points="10,10 100,10" fill="none" stroke="black" marker-end="url(#arrow3)"/> <!-- 右から左方向へ描画(orient="auto" のマーカー) --> <polyline points="100,30 10,30" fill="none" stroke="black" marker-end="url(#arrow3)"/> <!-- 上から下方向へ描画(orient="auto" のマーカー) --> <polyline points="10,50 10,80" fill="none" stroke="black" marker-end="url(#arrow3)"/> <!-- 下から上方向へ描画(orient="auto" のマーカー) --> <polyline points="30,80 30,50" fill="none" stroke="black" marker-end="url(#arrow3)"/> <!-- 上から右下方向へ描画(orient="auto" のマーカー) --> <polyline points="50,50 80,80" fill="none" stroke="black" marker-end="url(#arrow3)"/> <!-- 下から左上方向へ描画(orient="auto" のマーカー) --> <polyline points="100,80 70,50" fill="none" stroke="black" marker-end="url(#arrow3)"/> <!-- 水平方向両端へ描画(orient="auto-start-reverse"のマーカー) --> <polyline points="10,100 100,100" fill="none" stroke="black" marker-start="url(#arrow4)" marker-end="url(#arrow4)"/> <!-- 垂直方向両端へ描画(orient="auto-start-reverse"のマーカー) --> <polyline points="10,120 10,160" fill="none" stroke="black" marker-start="url(#arrow4)" marker-end="url(#arrow4)"/> <!-- 斜め方向両端へ描画(orient="auto-start-reverse"のマーカー) --> <polyline points="30,120 60,160" fill="none" stroke="black" marker-start="url(#arrow4)" marker-end="url(#arrow4)"/> <!-- 斜め方向両端へ描画(orient="auto-start-reverse"のマーカー) --> <polyline points="70,160 100,120" fill="none" stroke="black" marker-start="url(#arrow4)" marker-end="url(#arrow4)"/> </svg>
以下は orient 属性に角度を指定する例です。
右向きのマーカー図形を定義して、その定義に使用した path 要素を use 要素で利用して角度の異なるマーカーを定義しています。
<svg viewBox="0 0 160 40"> <defs> <!-- 右向き矢印のマーカーの定義 --> <marker id="arrow5" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="10" markerHeight="10" fill="green"> <path id="marker_arrow_right" d="M 0 0 L 10 5 L 0 10 z" /> </marker> <!-- 右向き矢印のマーカーの定義 --> <marker id="arrow6" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="10" markerHeight="10" fill="purple" orient="180"> <use href="#marker_arrow_right" /> </marker> <!-- 下向き矢印のマーカーの定義 --> <marker id="arrow7" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="10" markerHeight="10" fill="orange" orient="90"> <use href="#marker_arrow_right" /> </marker> </defs> <!-- 左から右方向へ描画(orient="auto" のマーカー) --> <polyline points="10,10 50,10 90,10" fill="none" stroke="black" marker-start="url(#arrow6)" marker-end="url(#arrow5)" marker-mid="url(#arrow7)"/> </svg>
markerUnits(マーカーサイズの基準の指定)
marker 要素の markerUnits 属性の初期値は strokeWidth になっているため、デフォルトでは描画されるマーカーは線幅に合わせて拡大されます。
markerUnits 属性に userSpaceOnUse を指定するとマーカーは線幅に合わせて拡大されず、markerWidth、markerHeight で指定した元のサイズで描画されます。
以下の場合、3番目と4番目の図形(矢印)のマーカーは userSpaceOnUse を指定しているので、線幅を変更してもマーカーの大きさは同じです。
<svg viewBox="0 0 240 160"> <!-- 三角矢印のマーカーの定義 --> <marker id="arrow8" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="10" markerHeight="10"> <path id="marker_arrow_right2" d="M 0 0 L 10 5 L 0 10 z" /> </marker> <!-- markerUnits="userSpaceOnUse" を指定した上記と同じ形状のマーカーの定義 --> <marker id="arrow9" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse"> <use href="#marker_arrow_right2" /> </marker> <!-- stroke-width="1" --> <line x1="20" y1="20" x2="120" y2="20" stroke="black" stroke-width="1" marker-end="url(#arrow8)" /> <!-- stroke-width="2" --> <line x1="20" y1="60" x2="120" y2="60" stroke="black" stroke-width="2" marker-end="url(#arrow8)" /> <!-- stroke-width="2" markerUnits="userSpaceOnUse" を指定したマーカー --> <line x1="20" y1="100" x2="120" y2="100" stroke="black" stroke-width="2" marker-end="url(#arrow9)" /> <!-- stroke-width="3" markerUnits="userSpaceOnUse" を指定したマーカー --> <line x1="20" y1="140" x2="120" y2="140" stroke="black" stroke-width="3" marker-end="url(#arrow9)" /> </svg>
変形 transform
transform 属性を使うと、要素に対して移動(translate)、回転(rotate)、伸縮(scale)、傾斜(skew)の変形処理ができます。
transform 属性では以下の transform 関数(変換関数)を使用して変形処理を行うことができます。変形処理の適用はネストされた要素(そのすべての子孫要素)にも影響を与えます。
g 要素に適用することでグループ化された要素にまとめて変形処理を適用することができます。
変換関数 | 意味 |
---|---|
translate | 要素を X 軸または Y 軸に対して指定された距離だけ移動させる関数 |
rotate | 原点を中心に時計回りに指定された角度(angle)だけ回転させる関数 |
scale | 要素を伸縮(拡大・縮小)させる関数 |
skewX skewY | X 軸または Y 軸に対して指定された角度だけ傾斜させる関数 |
matrix | 変換行列の形式で変形を指定する関数 |
変換関数は半角スペースまたはカンマで区切りで記述して複数の変形処理を適用することも可能です。
SVG2 では、transform 属性はプレゼンテーション属性となっていて CSS プロパティとして使用することができます(transform による変形処理を CSS から実行することができます)。
但し、CSS プロパティと SVG の transform 属性では構文や書式に違いがあるので注意が必要です。
また、HTML要素では要素に transform を実行する場合、ローカル座標系の原点は要素が構成するボックスの中央(50% 50%)にセットされて処理されますが、SVG 要素の場合、原点は SVG キャンバスの左上(0 0)になります。
translate 移動
translate 関数は、要素を X 軸または Y 軸に対して指定された距離だけ移動させます。その結果は座標系の位置に依存しません。
transform="translate(Tx [,Ty])"
- Tx : X 軸方向の移動距離
- Ty : Y 軸方向の移動距離
2つの値はカンマまたは半角スペースで区切ります。Ty が省略された場合、Ty の値は0とみなされます。
以下は X 軸方向に75、Y 軸方向に60 移動する例です。
<svg viewBox="0 0 300 200"> <rect x="20" y="20" width="100" height="50" fill="gold" /> <rect x="20" y="20" width="100" height="50" fill="blue" transform="translate(75 60)" /> </svg>
上記の transform 属性は以下のように記述しても同じです(複数の変換関数を半角スペースまたはカンマで区切りで記述可能)。
<rect x="20" y="20" width="100" height="50" fill="green" transform="translate(75), translate(0 60)" /> <!-- Y軸方向の(2つ目の)値が指定されていない場合は0とみなされます -->
style 属性(CSS)
SVG ユーザー単位 1 が 1px に相当する場合、上記の transform 属性は style 属性や style 要素(CSS)を使って以下のように記述しても同じ結果になります。
style 属性(CSS)の場合、2つの値はカンマで区切り単位を付ける必要があります。
<rect x="20" y="20" width="100" height="50" fill="green" style="transform:translate(75px, 60px) " />
要素に ID や Class を指定するなどして CSS で操作することもできます。
<rect id="translate_sample" x="20" y="20" width="100" height="50" fill="blue"/>
#translate_sample { transform:translate(75px, 60px); }
CSS には translateX() 及び translateY() という構文があるので以下のように記述しても同じ結果になります。CSS の場合、複数の変換関数を適用する場合はそれらを半角スペース区切りで記述します。
<rect x="20" y="20" width="100" height="50" fill="green" style="transform:translateX(75px) translateY(60px) " />
rotate 回転
rotate 関数は要素をその原点を中心に時計回りに指定された角度だけ回転させます。
HTML の場合、回転の中心はその要素の中央(transform-origin: 50% 50%)ですが、SVG の場合、回転の中心はキャンバスの左上(0 0)になります。
transform="rotate(angle [,Cx, Cy])"
- angle:回転角度
- Cx:回転の中心の X 座標
- Cy:回転の中心の Y 座標
Cx と Cy を省略した場合、SVG キャンバスの左上(0 0)が回転の中心になります。
以下はキャンバスの左上(0 0)を回転の中心として 30°回転する例です。
transform="rotate(30)" は transform="rotate(30, 0, 0)" と同じです。
<svg viewBox="0 0 300 200"> <rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" transform="rotate(30)" fill-opacity="0.5"/> </svg>
以下は図形の中央(100, 45)を中心点として30°回転する例です。
<svg viewBox="0 0 300 200"> <rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" transform="rotate(30, 100, 45)" fill-opacity="0.5"/> </svg>
変形の基準点をずらす
上記の回転は、以下のように図形の変形の基準となる点を一時的に原点(左上の 0 0)にずらして、変形(この場合は回転)して、その後元の位置に戻しても同じ結果になります。
複数の変形処理を指定した場合、図形に適用される変形処理は右側にある関数から適用されます。
<rect x="50" y="20" width="100" height="50" fill="blue" fill-opacity="0.5" transform="translate(100,45),rotate(30),translate(-100,-45)"/>
以下は図形の左上(50, 20)を中心点として30°回転する例です。
<svg viewBox="0 0 300 200"> <rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" fill-opacity="0.5" transform="rotate(30, 50, 20)"/> </svg>
以下のように、図形の変形の基準点を原点(左上の 0 0)にずらして、変形処理を適用してその後元の位置に戻しても同じ結果になります。
<rect x="50" y="20" width="100" height="50" fill="blue" fill-opacity="0.5" transform="translate(50,20),rotate(30),translate(-50,-20)"/>
style 属性(CSS)
上記の transform 属性は style 属性(CSS)を使って以下のように記述しても同じ結果になります。CSS の場合、単位として deg が必要です。
<!--(0 0)を中心点として回転 --> <rect x="50" y="20" width="100" height="50" fill="blue" style="transform: rotate(30deg);"/> <!--(100 45)を中心点として回転(SVG ユーザー単位 1 が 1px に相当する場合)--> <rect x="50" y="20" width="100" height="50" fill="blue" fill-opacity="0.5" style="transform: rotate(30deg); transform-origin: 100px 45px;"/> <!--(50 20)を中心点として回転(SVG ユーザー単位 1 が 1px に相当する場合)--> <rect x="50" y="20" width="100" height="50" fill="blue" fill-opacity="0.5" style="transform: rotate(30deg); transform-origin: 50px 20px;"/>
scale 拡大・縮小
scale 関数は、要素を指定された比率で伸縮(拡大・縮小)させます。
transform="scale(Sx [,Sy])"
- Sx:X 軸方向の伸縮する比率
- Sy:Y 軸方向の伸縮する比率
Sy が省略された場合は、Sx と同じ値であるとみなされます(同じ比率で伸縮できます)。
以下は X 軸方向に1.5倍、Y 軸方向に2倍に拡大する例です。
x 属性及び y 属性の値も指定された比率で拡大されるので、この例の場合は位置もずれます。図形の左上が 0 0 なら重なります。
<svg viewBox="0 0 300 200"> <rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" transform="scale(1.5,2)" fill-opacity="0.5"/> </svg>
変形の基準点をずらす
以下は図形の変形の基準となる点を translate( -50, -20) で一時的に原点(左上の 0 0)にずらして、変形(この場合は拡大)してその後元の位置に戻しすことで左上の頂点を重ねる例です。
<svg viewBox="0 0 300 200"> <rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" transform="translate(50,20),scale(1.5,2),translate(-50,-20)" fill-opacity="0.3"/> </svg>
transform に指定した関数は右側にある関数から順に適用されます。
<rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" transform="translate(-50,-20)" fill-opacity="0.3"/>
<rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" transform="scale(1.5,2),translate(-50,-20)" fill-opacity="0.3"/>
<rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" transform="translate(50,20),scale(1.5,2),translate(-50,-20)" fill-opacity="0.3"/>
複数の変形処理の適用
以下はどちらも同じ長方形を描画します
<rect x="50" y="20" width="100" height="50" transform="translate(50,20),scale(1.5,2),translate(-50,-20)" />
<g transform="translate(50,20),scale(1.5,2),translate(-50,-20)"> <rect x="50" y="20" width="100" height="50" /> </g>
また、上記は以下と機能的には同じことになります。変形処理は内側から順に適用されます。
<g transform="translate(50,20)"> <g transform="scale(1.5,2)"> <g transform="translate(-50,-20)"> <rect x="50" y="20" width="100" height="50"/> </g> </g> </g>
図形の中央を重ねる
以下は図形の中央(100, 45)を translate(-100,-45) で原点(左上の 0 0)にずらして、scale(1.5,2) で拡大してその後元の位置に戻しすことで2つの図形の中央を重ねる例です。
この例の場合、拡大した図形は描画領域(viewBox)からはみ出していしまうので、svg 要素に overflow: visible を指定してはみ出した部分を表示するようにしています。
<svg viewBox="0 0 300 200" style="overflow: visible"> <rect x="50" y="20" width="100" height="50" fill="gold" /> <rect x="50" y="20" width="100" height="50" fill="blue" fill-opacity="0.3" transform="translate(100,45),scale(1.5,2),translate(-100,-45)"/> </svg>
図形の中央を原点に配置
以下は図形の中央を原点に配置して scale() を使用する例です。
viewBox 及び図形の x, y 属性に負の値を指定して、図形の中央を原点(0 0)になるように配置しています。そのため、2つの図形は中央が重なるように配置されます。
以下の場合、scale() に引数を1つだけ指定しているのでX軸及びY軸方向に等倍に伸縮(この例では 0.5 なので縮小)されます。
<svg viewBox="-150 -100 300 200"> <rect x="-100" y="-50" width="200" height="100" fill="blue" fill-opacity="0.3" /> <rect x="-100" y="-50" width="200" height="100" fill="gold" transform="scale(0.5)" /> </svg>
style 属性(CSS)
transform 属性は style 属性を使って以下のように記述することができます。
<rect x="50" y="20" width="100" height="50" fill="blue" transform="scale(1.5,2)"/> <!-- 上記は以下のように記述することができます --> <rect x="50" y="20" width="100" height="50" fill="blue" style="transform: scale(1.5,2)" />
SVG ユーザー単位 1 が 1px に相当する場合、変形の基準点をずらす場合の例は以下のように記述することができます。
複数の変換関数を記述する際、style 属性で記述する場合は半角スペース区切りで指定する必要があります。
<rect x="50" y="20" width="100" height="50" fill="blue" transform="translate(50,20),scale(1.5,2),translate(-50,-20)"/> <!-- 上記は以下のように記述することができます --> <rect x="50" y="20" width="100" height="50" fill="blue" style="transform:translate(50px,20px) scale(1.5,2) translate(-50px,-20px)" /> <!-- transform-origin を使って以下のように記述しても同じになります --> <rect x="50" y="20" width="100" height="50" fill="blue" style="transform-origin: 50px 20px; transform:scale(1.5,2); "/>
CSS には scaleX() と scaleY() がありますが、SVG にはこれらに対応する関数はありません。
反転
scale() の値に負の値を設定することで図形を反転することができます。以下は X 軸方向に反転する例です。以下の例では図形の中央を原点(0 0)に配置しています。
また、g 要素に transform 属性を指定して polygon 及び text 要素に変形処理を適用しています。
Y 軸方向に反転させるには transform="scale(1,-1)"
とします。
<svg viewBox="-50 -50 100 100"> <g> <polygon points="0,-50 50,00 0,50" fill="blue" fill-opacity="0.3"/> <text x="10" y="3" fill="blue" font-size="8">ABC</text> </g> <g transform="scale(-1,1)"> <polygon points="0,-50 50,00 0,50" fill="gold"/> <text x="10" y="3" fill="blue" font-size="8">ABC</text> </g> </svg>
skewX skewY 傾斜
skewX() は X 軸を基準に、skewY() は Y 軸を基準に要素に指定された角度の傾斜変換を適用します。
transform="skewX(Sx)" transform="skewY(Sy)"
- Sx:X 軸に対する傾斜角度
- Sy:Y 軸に対する傾斜角度
以下は図形の中央を原点に配置して skewX(30) で X 軸を基準に図形に30度の傾斜変換を適用する例です。
<svg viewBox="-150 -100 300 200"> <rect x="-50" y="-50" width="100" height="100" fill="gold" /> <rect x="-50" y="-50" width="100" height="100" fill="blue" fill-opacity="0.5" transform="skewX(30)" /> </svg>
scale() 同様、スキュー操作の結果は要素の座標系の原点の位置によって異なります。
以下は図形の左上を原点に配置して skewX(30) で傾斜変換を適用する例です。
<svg viewBox="0 0 300 180"> <rect x="0" y="0" width="100" height="50" fill="gold" /> <rect x="0" y="0" width="100" height="50" fill="blue" fill-opacity="0.5" transform="skewX(30)" /> </svg>
以下は図形の左上の x 座標を 50 に配置して skewX(30) で傾斜変換を適用する例です。x 座標の値の分、ずれて描画されます。
<svg viewBox="0 0 300 200"> <rect x="50" y="50" width="100" height="100" fill="gold" /> <rect x="50" y="50" width="100" height="100" fill="blue" fill-opacity="0.5" transform="skewX(30)" /> </svg>
変形の基準点をずらす
以下は図形の左上の座標を translate( -50, -50) で一時的に原点(左上の 0 0)にずらして、傾斜変換を適用し、その後元の位置に戻しすことで左上の頂点を重ねる例です。
transform に指定した関数は右側にある関数から順に適用されます。
<svg viewBox="0 0 300 200"> <rect x="50" y="50" width="100" height="100" fill="gold" /> <rect x="50" y="50" width="100" height="100" fill="blue" fill-opacity="0.5" transform="translate(50,50),skewX(30),translate(-50,-50)" /> </svg>
以下は前述の例と同様、図形の中心を translate(-100,-100) で一時的に原点(左上の 0 0)にずらして、傾斜変換を適用し、その後元の位置に戻しすことで左上の頂点を重ねる例です。
transform に指定した関数は右側にある関数から順に適用されます。
<svg viewBox="0 0 300 200"> <rect x="50" y="50" width="100" height="100" fill="gold" /> <rect x="50" y="50" width="100" height="100" fill="blue" fill-opacity="0.5" transform="translate(100,100),skewX(30),translate(-100,-100)" /> </svg>
style 属性(CSS)
transform 属性は style 属性を使って以下のように記述することができます。
CSS の場合、角度の単位 deg を付ける必要があります。
<rect x="-50" y="-50" width="100" height="100" fill="blue" fill-opacity="0.5" transform="skewX(30)" /> <!-- 上記は以下のように記述することができます --> <rect x="-50" y="-50" width="100" height="100" fill="blue" fill-opacity="0.5" style="transform: skewX(30deg)" />
SVG ユーザー単位 1 が 1px に相当する場合、変形の基準点をずらす場合の例は以下のように記述することができます。
複数の変換関数を記述する際、style 属性で記述する場合は半角スペース区切りで指定する必要があります。
<rect x="50" y="50" width="100" height="100" fill="blue" fill-opacity="0.5" transform="translate(50,50),skewX(30),translate(-50,-50)" /> <!-- 上記は以下のように記述することができます --> <rect x="50" y="50" width="100" height="100" fill="blue" fill-opacity="0.5" style="transform:translate(50px,50px) skewX(30deg) translate(-50px,-50px)"/> <!-- transform-origin を使って以下のように記述しても同じです --> <rect x="50" y="50" width="100" height="100" fill="blue" fill-opacity="0.5" style="transform-origin: 50px 50px; transform:skewX(30deg)"/>
CSS には skew() という関数がありますが、SVG にはこれに対応する関数はありません。
skewX skewY 動作確認サンプル
以下は skewX 及び skewY にスライダーで角度の値を指定して動作を確認するサンプルです。
g 要素でグループ化した rect と line 要素にスキューを適用します。skewX または skewY に値を指定することができますが、このサンプルでは両方の処理を同時に指定することはできません。
<svg viewBox="-150 -150 300 300">
<rect x="-50" y="-50" width="100" height="100" fill="gold" />
<g transform="skewX(0)">
<rect x="-50" y="-50" width="100" height="100" fill="blue"/>
<line x1="0" y1="-150" x2="0" y2="150" stroke="blue"/>
<line x1="-150" y1="0" x2="150" y2="0" stroke="red"/>
</g>
</svg>
変形 transform についての詳細は以下のサイトが参考になります。
transform 属性を使った例
以下は rect 要素に transform 属性を適用した矩形を g 要素でグループ化して立方体を描画し、その立方体を use 要素で再利用(複製)して描画した図形です。
以下が立方体のコードで3つの rect 要素で構成されています。
<svg viewBox="0 0 80 60"> <defs> <g id="cube0" class="cube-unit"> <rect width="21" height="24" fill="#73CC51" stroke="#348315" transform="skewY(30)"/> <rect width="21" height="24" fill="#286411" stroke="#348315" transform="skewY(-30) translate(21 24.3)"/> <rect width="21" height="21" fill="#4DBC22" stroke="#348315" transform="scale(1.41,.81) rotate(45) translate(0 -21)"/> </g> </defs> <use href="#cube0" x="20" y="20"/> </svg>
以下が全体のコードです。以下のサイトを参考にさせていただきました(ほぼそのままです)。
css-tricks.com:Use and Reuse Everything in SVG(詳細はこちらのサイトを御覧ください)
グラデーション Gradient
SVG では図形やテキストの塗りやストロークにグラデーションを適用することができます。
グラデーションとはある色から別の色へ継続的でなめらかなに推移する色のことです。英語では Gradient(グラディエント)と言い、Gradient には勾配(こうばい)や傾斜という意味があります。
CSS3 のグラデーションでは背景関連プロパティ(background-image や background)に直接グラデーションの定義を指定しますが、SVG では defs 要素内で別途グラデーションを定義しておき、 グラフィックス要素(図形やテキスト)の塗りやストロークからその値を参照します。
具体的には、defs 要素内で linearGradient 要素(線形グラデーション)や radialGradient 要素(円形グラデーション)を使ってグラデーションを定義します。
その際に定義した要素に id 属性を設定して、その id の値をグラデーションを適用するグラフィックス要素の fill 属性や stroke 属性から url 関数を使って参照することでグラデーションが描画されます。
<svg viewBox="0 0 320 150"> <defs><!-- defs 要素でグラデーションを定義 --> <linearGradient id="gradient02"><!-- 線形グラデーションの定義 --> <stop offset="0%" stop-color="lightblue" /> <stop offset="100%" stop-color="lightpink" /> </linearGradient> <radialGradient id="gradient03"><!-- 円形グラデーションの定義 --> <stop offset="5%" stop-color="lightblue"/> <stop offset="95%" stop-color="lightpink"/> </radialGradient> </defs> <!-- 塗り(fill 属性)からグラデーションの id を参照 --> <rect fill="url(#gradient02)" x="10" y="10" width="80" height="80" /> <!-- ストローク(stroke 属性)からグラデーションの id を参照 --> <rect fill="none" stroke="url(#gradient02)" stroke-width="10" x="120" y="15" width="70" height="70" /> <!-- 塗り(fill 属性)からグラデーションの id を参照 --> <circle fill="url(#gradient03)" cx="260" cy="50" r="40"/> <!-- 塗り(fill プロパティ)からグラデーションの id を参照 --> <text x="10" y="140" font-size="30" fill="url(#gradient02)" >Gradient!</text> </svg>
SVG では以下の2種類のグラデーションが用意されています(SVG2 では meshGradient 要素を使って定義するメッシュグラデーションが用意されています)。
- 線形グラデーション : linearGradient 要素を使って定義
- 円形(放射型)グラデーション : radialGradient 要素を使って定義
グラデーションの色の指定
グラデーションの色の変化(色の指定)は stop 要素を使って定義します。
<linearGradient id="gradient02"> <stop offset="0%" stop-color="lightblue" /><!-- 開始色を水色に --> <stop offset="100%" stop-color="lightpink" /><!-- 終了色を薄ピンク色に --> </linearGradient>;
グラデーションは stop 要素で指定された色とその位置及び勾配ベクトル(グラデーションの変化する向きと範囲を表す線分)を元に描画されます。
線形グラデーションの場合、デフォルトの勾配ベクトルは左から右方向の線分で、円形グラデーションの場合は円の中心から外側に向かう線分です。
stop 要素
stop 要素はグラデーションで使用する色とその位置を stop-color 属性と offset 属性のペアで定義します。stop 要素は常に linearGradient または radialGradient 要素の子要素として使われます。
グラデーションの効果が得られるようにするには、少なくとも2つ以上の stop 要素が定義されている必要があります(1つだけの場合は単色の均一な塗りになります)。
また、stop 要素で設定された範囲外はデフォルトでは単色の均一な塗りになります。
属性 | 意味 |
---|---|
offset | 勾配ベクトルにおける色の位置をパーセントまたは 0〜1 の範囲の数値(比率)で指定します。勾配ベクトルの始点が0%(または0)、終点が100%(または1)。初期値:0 |
stop-color | グラデーションストップ(stop 要素)の色を指定します。初期値:black |
stop-opacity | グラデーションストップ(stop 要素)の不透明度を指定します。初期値:1 |
offset 属性については以下のような特徴(制約)があります。
- 0(または 0%)より小さい offset の値は 0% に切り上げられ、 1(または 100%)より大きい offset の値は 100% に切り下げられます
- 各グラデーションストップの offset の値は、前の offset の値より大きくします
- 2つのグラデーションストップが同じ offset の値を持つ場合、後の方のグラデーションストップが境目から後の色を制御します(境目で急激に色が変化します)
以下は linearGradient で6つの stop 要素を使ってそれぞれの色を等間隔に指定した例です。
<div style="max-width:300px"> <svg viewBox="0 0 120 70" style="overflow:visible"> <defs> <linearGradient id="gradient04" gradientUnits="userSpaceOnUse" x1="10" y1="35" x2="110" y2="35">> <stop offset="0%" stop-color="red" /> <stop offset="20%" stop-color="orange" /> <stop offset="40%" stop-color="yellow" /> <stop offset="60%" stop-color="green" /> <stop offset="80%" stop-color="blue" /> <stop offset="100%" stop-color="mediumpurple" /> </linearGradient> </defs> <rect x="0" y="0" width="120" height="70" fill="url(#gradient04)" /> </svg> </div>
この例では linearGradient 要素の gradientUnits 属性に userSpaceOnUse を指定して、勾配ベクトルの始点の位置を x1=10、終点の位置を x2=110 としてそれぞれキャンバス(表示領域)の端から 10 の位置にしています。そのため、左端から0%の位置まで及び右端から 100%の位置までの勾配ベクトルの範囲外は単色での塗りになっています。
以下は3番目と4番目の stop 要素の offset 属性に同じ値を指定した例です。
3番目と4番目は重なり、境目で4番目の stop 要素の色(blue)に急激に変化しています。
<div style="max-width:300px"> <svg viewBox="0 0 120 70" style="overflow:visible"> <defs> <linearGradient id="gradient05" gradientUnits="userSpaceOnUse" x1="10" y1="35" x2="110" y2="35">> <stop offset="0%" stop-color="violet" /> <stop offset="20%" stop-color="lightblue" /> <stop offset="60%" stop-color="lightgreen" /><!-- 同じ offset 値 --> <stop offset="60%" stop-color="blue" /><!-- 同じ offset 値 --> <stop offset="100%" stop-color="red" /> </linearGradient> </defs> <rect x="0" y="0" width="120" height="70" fill="url(#gradient05)" /> </svg> </div>
この例でも前述の例同様、gradientUnits 属性に userSpaceOnUse を指定して、勾配ベクトルの始点と終点の位置をそれぞれキャンバス(表示領域)の端から 10 の位置にしています。
以下は radialGradient で3つの stop 要素を指定した例です。
この例の場合、offset に 0% を指定した stop 要素がないので0%〜10%は単色の塗りになり、また、100%を指定した stop 要素がないので80%〜100%は単色の塗りになります。
<div style="max-width: 300px;"> <svg viewBox="0 0 120 120" style="overflow:visible"> <defs> <radialGradient id="gradient06">> <stop offset="10%" stop-color="gold" /> <stop offset="50%" stop-color="lightblue" /> <stop offset="80%" stop-color="blue" /> </radialGradient> </defs> <circle cx="50" cy="50" r="50" fill="url(#gradient06)"/> </svg> </div>
stop 要素では不透明度を指定することもできます。以下は stop-opacity 属性を使って不透明度を指定した例です。
<svg width="200px" height="200px" viewBox="0 0 100 100" style="border:1px solid #ddd;"> <defs> <radialGradient id="gradient07">> <stop offset="30%" stop-color="gold" /> <stop offset="100%" stop-color="blue" stop-opacity="0"/> </radialGradient> </defs> <circle cx="50" cy="50" r="50" fill="url(#gradient07)"/> </svg>
線形グラデーション linearGradient
線形グラデーションを適用するには defs 要素内で linearGradient 要素を使用してグラデーションを定義します。
linearGradient 要素には参照のために使用する id 属性を定義し、必要に応じて以下のような専用属性を指定することができます。
属性 | 意味 |
---|---|
gradientUnits | グラデーションを適用する座標系。
|
gradientTransform | グラデーションの変形を指定。設定する関数は transform 属性と共通。 |
x1 | 勾配ベクトルを定義する(始点の X 軸方向の)値。初期値:0%(0) |
y1 | 勾配ベクトルを定義する(始点の Y 軸方向の)値。初期値:0%(0) |
x2 | 勾配ベクトルを定義する(終点の X 軸方向の)値。初期値:100%(1) |
y2 | 勾配ベクトルを定義する(終点の Y 軸方向の)値。初期値:0%(0) |
spreadMethod | グラデーションの繰り返しの方法の指定。
|
href | xlink:href | 別のグラデーションを参照して利用する場合にそのグラデーションの URL 指定。xlink:href は SVG2 では非推奨 |
MDN SVG 要素リファレンス linearGradient
勾配ベクトル
グラデーションは勾配(こうばい)ベクトルに沿って変化します。ベクトルとは向きと大きさを持つ量のことで線分で表されます。
勾配ベクトル(gradient vector)はグラデーションの変化する方向と範囲を表す線分で、方向や範囲は x1、y1、x2、y2 属性で定義することができます。
勾配ベクトルの始点は (x1, y1) 、終点は (x2, y2) で定義されます。x1 ,y1, x2, y2 を省略した場合は始点に (0%, 0%) 、終点に (100%, 0%)を指定したことになり左から右方向への水平の線分になります。
<linearGradient id="my_gradient"> ・・・ </linearGradient> <!-- 上記は以下と同じこと --> <linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="my_gradient"> ・・・ </linearGradient> <!-- 以下のように 0〜1 の数値で指定することもできます --> <linearGradient x1="0" y1="0" x2="1" y2="0" id="my_gradient"> ・・・ </linearGradient>
以下は勾配ベクトルのイメージを line 要素で描画した例です。line 要素には linearGradient 要素の x1、y1、x2、y2 属性と同じ値を指定しています。
この例では勾配ベクトルのイメージがが垂直方向中央に位置するように viewBox="0 -100 300 200" としています。また、方向がわかりやすいようにマーカーで矢印を追加しています。
<svg viewBox="0 -100 300 200"> <defs> <linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="my_gradient"> <stop offset="20%" stop-color="red" /> <stop offset="80%" stop-color="blue" /> </linearGradient> </defs> <rect x="0" y="-100" width="300" height="200" fill="url(#my_gradient)"/> <!-- 勾配ベクトルを表す線分の描画 --> <line x1="0%" y1="0%" x2="100%" y2="0%" stroke="silver" stroke-width="2" marker-end="url(#gold_arrow)"/> </svg>
グラデーションの角度
グラデーションの角度を変更するには、x1 ,y1, x2, y2 属性を指定して勾配ベクトルの角度を変更します。
または、gradientTransform 属性を使って変更することもできます。
以下はデフォルトの角度のグラデーション(と勾配ベクトル)の例です。
<svg viewBox="0 0 300 200"> <defs> <linearGradient id="gradient08"> <stop offset="0%" stop-color="#55D0A9" /> <!-- 薄緑系の色 --> <stop offset="50%" stop-color="#EE6600" /> <!-- オレンジ系の色 --> <stop offset="100%" stop-color="#FAF421" /> <!-- 黄色系の色 --> </linearGradient> </defs> <rect x="0" y="0" width="300" height="200" fill="url(#gradient08)" /> <!-- 勾配ベクトルを表す線分の描画 --> <line x1="0%" y1="0%" x2="100%" y2="0%" stroke="black" stroke-width="2" marker-end="url(#marker)"/> </svg>
以下は x1="0%" y1="0%" x2="0%" y2="100%" を指定して勾配ベクトルの角度を上から下への垂直方向に変更して垂直方向のグラデーションにする例です。
<svg viewBox="0 0 300 200"> <defs> <linearGradient id="gradient09" x1="0%" y1="0%" x2="0%" y2="100%"> <stop offset="0%" stop-color="#55D0A9" /> <stop offset="50%" stop-color="#EE6600" /> <stop offset="100%" stop-color="#FAF421" /> </linearGradient> </defs> <rect x="0" y="0" width="300" height="200" fill="url(#gradient08)" /> <!-- 勾配ベクトルを表す線分の描画 --> <line x1="0%" y1="0%" x2="0%" y2="100%" stroke="black" stroke-width="2" marker-end="url(#marker)"/> </svg>
以下は x1="0%" y1="0%" x2="100%" y2="100%" を指定して勾配ベクトルの角度を斜め右下方向に変更する例です。
<svg viewBox="0 0 300 200"> <defs> <linearGradient id="gradient10" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" stop-color="#55D0A9" /> <stop offset="50%" stop-color="#EE6600" /> <stop offset="100%" stop-color="#FAF421" /> </linearGradient> </defs> <rect x="0" y="0" width="300" height="200" fill="url(#gradient10)" /> <!-- 勾配ベクトルを表す線分の描画 --> <line x1="0%" y1="0%" x2="100%" y2="100%" stroke="black" stroke-width="2" marker-end="url(#marker)"/> </svg>
以下は前述の例と同じグラデーションを正方形の図形に適用する例です。この場合、正方形なので斜め右下45度のグラデーションになります。
<svg viewBox="0 0 300 300"> <rect x="0" y="0" width="300" height="300" fill="url(#gradient10)" /> <!-- 勾配ベクトルを表す線分の描画 --> <line x1="0%" y1="0%" x2="100%" y2="100%" stroke="black" stroke-width="2" marker-end="url(#marker)"/> </svg>
gradientTransform
gradientTransform 属性ではグラデーションの変形を指定することができます。設定する関数は transform 属性と共通です。
以下はデフォルトの linearGradient 要素の gradientTransform 属性に rotate 関数を指定して45度のグラデーションに変形する例です。
<svg viewBox="0 0 300 300"> <defs> <linearGradient id="gradient11" gradientTransform="rotate(45)"> <stop offset="0%" stop-color="#55D0A9" /> <stop offset="50%" stop-color="#EE6600" /> <stop offset="100%" stop-color="#FAF421" /> </linearGradient> </defs> <rect x="0" y="0" width="300" height="300" fill="url(#gradient11)" /> <!-- 勾配ベクトルを表す線分の描画 --> <line x1="0%" y1="0%" x2="100%" y2="0%" transform="rotate(45)" stroke="black" stroke-width="2" marker-end="url(#marker)"/> </svg>
以下は回転の中心の座標に(0.5, 0.5)を指定した例です。
<svg viewBox="0 0 300 300"> <defs> <linearGradient id="gradient12" gradientTransform="rotate(45, 0.5, 0.5)"> <stop offset="0%" stop-color="#55D0A9" /> <stop offset="50%" stop-color="#EE6600" /> <stop offset="100%" stop-color="#FAF421" /> </linearGradient> </defs> <rect x="0" y="0" width="300" height="300" fill="url(#gradient12)" /> </svg>
線形グラデーション 動作確認サンプル
以下は x1 ,y1, x2, y2 属性の値や stop 要素の offset 属性の値を変更してグラデーションがどのように変化するかを確認するサンプルです。
グラデーションはグラデーションの変化する向きと範囲を表す勾配ベクトル及び stop 要素で指定された色とその位置を元に描画されます(実際にはその他の gradientTransform や gradientUnits、spreadMethod 属性によっても変わってきます)。
勾配ベクトルは実際には表示されませんが、以下のサンプルでは赤い矢印の黒の線で表しています。
<svg viewBox="0 0 300 200"> <defs> <linearGradient id="gradient_sample" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stop-color="#55D0A9" /> <stop offset="50%" stop-color="#EE6600" /> <stop offset="100%" stop-color="#FAF421" /> </linearGradient> </defs> <rect x="0" y="0" width="300" height="200" fill="url(#gradient_sample)" /> <!-- 勾配ベクトルを表す線分の描画 --> <line x1="0%" y1="0%" x2="100%" y2="100%" stroke="black" stroke-width="2" marker-end="url(#arrow_red)"/> </svg>
gradientUnits
gradientUnits 属性では、グラデーションを適用する座標系を指定することができます。
gradientUnits 属性を省略した場合や gradientUnits 属性に objectBoundingBox を指定した場合は図形ごとのローカルな座標系(図形を囲む矩形)にグラデーションが適用されます。
この場合、x1、y1、x2、y2 属性の座標の値は相対的な 0% から100%(または 0 から 1)の間で指定する必要があり、その値は自動的に対象のオブジェクトの大きさに合わせて調整されます。
<svg viewBox="0 0 450 100"> <defs> <linearGradient id="gradient13" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%" > <stop offset="0%" stop-color="#B34E7E" /> <stop offset="50%" stop-color="#FFF8B8" /> <stop offset="100%" stop-color="#01B3ED" /> </linearGradient> </defs> <rect x="0" y="0" width="100" height="100" fill="url(#gradient13)" stroke="black"/> <rect x="150" y="0" width="150" height="100" fill="url(#gradient13)" stroke="black"/> <circle cx="400" cy="50" r="50" fill="url(#gradient13)" stroke="black" /> </svg>
gradientUnits 属性に userSpaceOnUse を指定すると、グラデーションはユーザー座標系(利用座標系)に適用されます。座標の値は絶対的な値を指定します(パーセントで指定した場合は現在のビューポートに対して相対的な値を表します)。
以下は x1="0" y1="0" x2="400" y2="0" を指定してキャンバス(表示領域)を基準に水平方向のグラデーションを定義してそれぞれの図形で利用する例です。
複数の図形で同じ勾配ベクトルを使用することができます。
<svg viewBox="0 0 400 200"> <defs> <linearGradient id="gradient14" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="400" y2="0"> <stop offset="0%" stop-color="#B34E7E" /> <stop offset="50%" stop-color="#FFF8B8" /> <stop offset="100%" stop-color="#01B3ED" /> </linearGradient> </defs> <rect x="0" y="0" width="100" height="100" fill="url(#gradient14)" stroke="black"/> <rect x="120" y="0" width="160" height="100" fill="url(#gradient14)" stroke="black" /> <circle cx="350" cy="50" r="50" fill="url(#gradient14)" stroke="black"/> <rect x="50" y="50" width="150" height="100" fill="url(#gradient14)" stroke="black"/> <rect x="220" y="80" width="160" height="100" fill="url(#gradient14)" stroke="black" /> </svg>
以下は x1="0" y1="0" x2="0" y2="200" を指定した垂直方向のグラデーションの例です。
<svg viewBox="0 0 400 200" style="overflow: visible;"> <defs> <linearGradient id="gradient15" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="0" y2="200"> <stop offset="0%" stop-color="#B34E7E" /> <stop offset="50%" stop-color="#FFF8B8" /> <stop offset="100%" stop-color="#01B3ED" /> </linearGradient> </defs> <rect x="0" y="0" width="100" height="100" fill="url(#gradient15)" stroke="black"/> <rect x="120" y="0" width="160" height="100" fill="url(#gradient15)" stroke="black" /> <circle cx="350" cy="50" r="50" fill="url(#gradient15)" stroke="black"/> <rect x="50" y="50" width="150" height="100" fill="url(#gradient15)" stroke="black"/> <rect x="220" y="80" width="160" height="100" fill="url(#gradient15)" stroke="black"/> <text x="-10" y="-10" font-size="12" fill="#999">(0, 0)</text> </svg>
図形を基準にグラデーションを定義する場合はデフォルトの objectBoundingBox を、キャンバス(表示領域)を基準にグラデーションを定義する場合や複数の図形で同じ勾配ベクトルを使用したい場合は userSpaceOnUse を指定します。
spreadMethod
spreadMethod 属性はグラデーションの繰り返しの方法を指定します。
デフォルト(spreadMethod 属性を省略した場合や値に pad を指定した場合)は繰り返しは行われず、勾配ベクトルの範囲外の色はグラデーションの両端の色で均一に塗りつぶされます(グラデーションの開始前は最初の offset の色で、終端に達すると最後の offset の色で残りの部分が塗りつぶされます)。
repeat を指定すると、勾配ベクトルの0%~100%の範囲の色が繰り返し適用され、対象領域が塗り潰されるまで勾配ベクトルが延伸されます。
reflect を指定すると、奇数番目の繰り返しのグラデーション(勾配ベクトル)の方向が逆になり、対象領域が塗り潰されるまで勾配ベクトルが延伸され、継ぎ目のないグラデーションになります。
以下は x1="0%" y1="0%" x2="50%" y2="0%" を指定してグラデーションの範囲を水平方向50%にして、勾配ベクトルの範囲外を spreadMethod 属性で指定する例です。初期状態では spreadMethod="repeat" を指定しています。
<svg viewBox="0 0 300 200">
<defs>
<linearGradient id="gradient16" x1="0%" y1="0%" x2="50%" y2="0%"
spreadMethod="repeat">
<stop offset="0%" stop-color="#A08FD5" />
<stop offset="100%" stop-color="#F5E866" />
</linearGradient>
</defs>
<rect x="0" y="0" width="300" height="200" fill="url(#gradient16)"/>
</svg>
pad(デフォルト) repeat reflect
以下は x1="33.3%" y1="0%" x2="66.6%" y2="0%" を指定してグラデーションの範囲を水平方向33.3%にして、勾配ベクトルの範囲外を spreadMethod 属性で指定する例です。
<svg viewBox="0 0 300 200">
<defs>
<linearGradient id="gradient17" x1="33.3%" y1="0%" x2="66.6%" y2="0%"
spreadMethod="repeat">
<stop offset="0%" stop-color="#A08FD5" />
<stop offset="100%" stop-color="#F5E866" />
</linearGradient>
</defs>
<rect x="0" y="0" width="300" height="200" fill="url(#gradient17)"/>
</svg>
pad(デフォルト) repeat reflect
以下は gradientUnits 属性に userSpaceOnUse を指定して x1="25" y1="0" x2="100" y2="0" としてグラデーションの範囲を設定する例です。
<svg viewBox="0 0 300 200">
<defs>
<linearGradient id="gradient18" gradientUnits="userSpaceOnUse"
x1="25" y1="0" x2="100" y2="0"
spreadMethod="repeat">
<stop offset="0%" stop-color="#A08FD5" />
<stop offset="100%" stop-color="#F5E866" />
</linearGradient>
</defs>
<rect x="0" y="0" width="300" height="200" fill="url(#gradient18)"/>
</svg>
pad(デフォルト) repeat reflect
href(xlink:href)
href(または xlink:href)属性を使うと、別の linearGradient 要素を参照して利用すことができます。
SVG2 では xlink:href は非推奨になっています。
以下は前述のグラデーション(linearGradient 要素)を参照して利用する例です。
この例では spreadMethod 属性の値を上書きして gradientTransform 属性を追加してグラデーションの角度を変更しています。
<svg viewBox="0 0 300 200"> <defs> <linearGradient id="gradient19" href="#gradient18" spreadMethod="reflect" gradientTransform="rotate(45)" > </linearGradient> </defs> <rect x="0" y="0" width="300" height="200" fill="url(#gradient19)"/> </svg>
円形グラデーション radialGradient
radialGradient 要素を使って円形(放射状)グラデーションを定義することができます。
勾配ベクトルを定義する属性名が異なりますが、他の使い方は linearGradient 要素とほぼ同じです。
円形グラデーションの場合、勾配ベクトルはグラデーションの中心点と半径で定義されます。
線形グラデーション同様、radialGradient 要素には参照のために使用する id 属性を定義し、必要に応じて以下のような専用属性を指定することができます。
属性 | 意味 |
---|---|
gradientUnits | グラデーションを適用する座標系。
|
gradientTransform | グラデーションの変形を指定。設定する関数は transform 属性と共通。 |
cx | グラデーションの中心点の位置(X 軸方向の値)。初期値:50%(0.5) |
cy | グラデーションの中心点の位置(Y 軸方向の値)。初期値:50%(0.5) |
r | グラデーションの半径の値。初期値:初期値:50%(0.5) |
fx | グラデーションの焦点の位置(X 軸方向の値)。初期値:cx と同じ |
fy | グラデーションの焦点の位置(Y 軸方向の値)。初期値:cy と同じ |
fr | グラデーションの焦点の半径の値。初期値:0%(0)。※まだ使えない? |
spreadMethod | グラデーションの繰り返しの方法の指定。
|
href | xlink:href | 別のグラデーションを参照して利用する場合にそのグラデーションンの URL 指定。xlink:href は SVG2 では非推奨 |
MDN SVG 要素リファレンス radialGradient
勾配ベクトル
勾配ベクトルは円形グラデーションの場合、グラデーションの中心点(cx、cy 属性)と半径(r 属性)で定義され、円の中心から外側に向かう線分になります。
<svg viewBox="0 0 200 200"> <defs> <radialGradient id="radial_gradient1" cx="50%" cy="50%" r="50%"> <stop offset="0%" stop-color="white"/> <stop offset="100%" stop-color="green"/> </radialGradient> </defs> <circle cx="100" cy="100" r="100" fill="url(#radial_gradient1)" /> <circle cx="50%" cy="50%" r="5" fill="red" /> </svg>
以下は offset="50%" の stop 要素を追加してグラデーションに黄色を追加した例です。
cx、cy、r を省略した場合は cx="50%" cy="50%" r="50%" を指定したのと同じです。
<svg viewBox="0 0 200 200"> <defs> <radialGradient id="radial_gradient2"> <stop offset="0%" stop-color="white"/> <stop offset="50%" stop-color="yellow"/> <stop offset="100%" stop-color="green"/> </radialGradient> </defs> <circle cx="100" cy="100" r="100" fill="url(#radial_gradient2)" /> <circle cx="50%" cy="50%" r="3" fill="red" /> <circle cx="75%" cy="50%" r="3" fill="orange" /> </svg>
グラデーションの焦点
円形グラデーションにはグラデーションの焦点を変更する fx、fy 属性とグラデーションの焦点の半径を指定する fr 属性があります。
焦点はグラデーションの0%の色が適用される点のことで、デフォルトでは cx、cy と同じ値で、fr の初期値は 0 です(fr はまだ正式には使えないようです)。
<svg viewBox="0 0 200 200"> <defs> <radialGradient id="radial_gradient2" cx="50%" cy="50%" r="50%" fx="25%" fy="25%" fr="10%"> <stop offset="0%" stop-color="white"/> <stop offset="100%" stop-color="green"/> </radialGradient> </defs> <circle cx="100" cy="100" r="100" fill="url(#radial_gradient2)" /> <circle cx="50%" cy="50%" r="3" fill="red" /> <circle cx="25%" cy="25%" r="3" fill="blue" /> <circle cx="25%" cy="25%" r="10%" fill="transparent" stroke="gray" stroke-dasharray="2"/> </svg>
但し、fx、fy、 fr 属性で定義した焦点の円(上図の点線の円)が cx、cy、r で定義した円の外側にある(はみ出した)場合はグラデーションが正しく描画されません。
グラデーションの焦点を少しずらすことで球体のような表現も可能です。
また、勾配ベクトルを定義する属性に指定する値は、線形グラデーション同様、0〜1 の数値で指定することもできます。
<svg viewBox="0 0 200 200"> <defs> <radialGradient id="radial_gradient4" cx="0.5" cy="0.5" r="0.5" fx="0.35" fy="0.35" fr="0.06"> <stop offset="0%" stop-color="white"/> <stop offset="100%" stop-color="darkseagreen"/> </radialGradient> </defs> <circle cx="100" cy="100" r="100" fill="url(#radial_gradient4)" /> </svg>
gradientUnits
gradientUnits 属性を省略するかデフォルトの objectBoundingBox の場合は、描画領域の縦横比に応じた楕円のグラデーションになります。
<svg viewBox="0 0 300 200"> <defs> <radialGradient id="radial_gradient5" gradientUnits="objectBoundingBox"> <stop offset="0%" stop-color="#B34E7E"/> <stop offset="50%" stop-color="#FFF8B8"/> <stop offset="100%" stop-color="#01B3ED"/> </radialGradient> </defs> <ellipse cx="150" cy="100" rx="150" ry="100" fill="url(#radial_gradient5)"/> </svg>
gradientUnits 属性が userSpaceOnUse の場合は、正円のグラデーションになります。
※ Safari や iOS では中心が下の方にずれてしまいます。
<svg viewBox="0 0 300 200"> <defs> <radialGradient id="radial_gradient6" gradientUnits="userSpaceOnUse"> <stop offset="0%" stop-color="#B34E7E"/> <stop offset="50%" stop-color="#FFF8B8"/> <stop offset="100%" stop-color="#01B3ED"/> </radialGradient> </defs> <ellipse cx="150" cy="100" rx="150" ry="100" fill="url(#radial_gradient6)"/> </svg>
spreadMethod
spreadMethod 属性を省略した場合は、グラデーションが終端に達すると最後の offset の色で残りの部分を塗りつぶす pad が適用されます。
repeat を指定すると残りの部分にグラデーションを繰り返します。
reflect を指定すると残りの部分にグラデーションを繰り返しますが、offset が 100% の色から始まり 0% の色へ戻るように逆向きのグラデーションを行い、その後逆向きのグラデーションを行うことを繰り返します。
以下は図形の下のボタンで spreadMethod 属性の値を変更して確認するサンプルです。
※ Safari や iOS では機能しないようです。
<svg viewBox="0 0 200 200">
<defs>
<radialGradient id="radial_gradient7"
cx="0.5" cy="0.5" r="0.4" fx=".25" fy=".25"
spreadMethod="repeat">
<stop offset="0%" stop-color="#B34E7E"/>
<stop offset="50%" stop-color="#FFF8B8"/>
<stop offset="100%" stop-color="#01B3ED"/>
</radialGradient>
</defs>
<rect x="0" y="0" width="200" height="200" fill="url(#radial_gradient7)"/>
</svg>
pad(デフォルト) repeat reflect
円形グラデーション 動作確認サンプル
以下は radialGradient の属性の値や stop 要素の offset 属性の値を変更してグラデーションがどのように変化するかを確認するサンプルです。
<svg viewBox="0 0 300 300"> <defs> <radialGradient id="rg_sample" cx="50%" cy="50%" r="50%" fx="50%" fy="50%" fr="0%" gradientUnits="objectBoundingBox" spreadMethod="pad"> <stop offset="0%" stop-color="#E1568B"/> <stop offset="50%" stop-color="#F8DF00"/> <stop offset="100%" stop-color="#635DFF"/> </radialGradient> </defs> <rect x="0" y="0" rx="0" ry="0" width="300" height="300" fill="url(#rg_sample)"/> </svg>
※ rect 要素の rx と ry はどちらかの値が 0 の場合は角丸にならないので、両方の値を 0 より大きくする必要があります。
パターン pattern
グラデーションと同様、図形やテキスト(グラフィックス要素)の塗りやストロークにパターンを適用することができます。
パターンは defs 要素内で pattern 要素を使って定義し、グラフィックス要素の fill や stroke プロパティから pattern 要素を参照します。
pattern 要素の内部には子要素として基本図形要素を含めることができ、それらの図形にグラデーションや不透明度などを設定することができます。
以下はグラデーションを適用した circle 要素でパターンを定義して、rect 要素の fill 属性で参照して塗りにパターンを適用しています。
<div style="max-width: 200px;"> <svg viewBox="0 0 100 100"> <defs> <radialGradient id="my_gradient" cx="0.5" cy="0.5" r="0.5" fx="0.35" fy="0.35" fr="0.06"> <stop offset="0%" stop-color="white"/> <stop offset="100%" stop-color="mediumpurple"/> </radialGradient> <!-- 以下がパターンの定義 --> <pattern id="my_pattern" x="0" y="0" width="0.25" height="0.25"> <circle cx="10" cy="10" r="9" fill="url(#my_gradient)"/> </pattern> </defs> <!-- rect 要素に上記で定義したパターンを適用 --> <rect fill="url(#my_pattern)" x="0" y="0" width="100" height="100"/> </svg> </div>
pattern 要素には参照のために使用する id 属性を定義し、以下のような属性を指定することができます。
属性 | 意味 |
---|---|
patternUnits | pattern 要素の x, y, width, height 属性の座標系を定義する属性で以下を指定できます。
|
patternContentUnits | pattern 要素のコンテンツ(内容:パターンに使用する図形要素)の座標系を定義する属性で以下を指定できます。※ viewBox 属性が指定されている場合、この属性(に指定した値)は無視されます(効果がありません)。
|
x | パターンの位置(X 座標シフト)を数値またはパーセントで指定。初期値:0 |
y | パターンの位置(Y 座標シフト)を数値またはパーセントで指定。初期値:0 |
width | パターンの幅を数値またはパーセントで指定。値を 0 にすると要素は描画されません。初期値:0 |
height | パターンの高さを数値またはパーセントで指定。値を 0 にすると要素は描画されません。初期値:0 |
viewBox | パターンの描画領域(パターンとして切り出す範囲)の定義 |
preserveAspectRatio | 縦横比が異なる場合の拡大縮小方法。初期値:xMidYMid meet |
patternTransform | transform 関数(変換関数)を使用してパターンの変換(変形)を指定。 |
href(xlink:href) | 別のパターンを参照して利用する場合にそのパターンの URL 指定。xlink:href は SVG2 では非推奨 |
pattern 要素の x, y, width, height 属性に指定する値は、patternUnits 属性の値により比率で指定するか描画領域の座標で指定するかかを選択できます。
pattern 要素の内容(パターンに使用する図形要素)に指定する値も同様に patternContentUnits 属性の値により比率で指定するか描画領域の座標で指定するかかを選択できます。
また、pattern 要素の内容(図形)に指定する値は patternContentUnits の代わりに viewBox 属性を使って定義することもできます。
いろいろな方法がありますが、パターンに適した方法や好みで選択すると良いかと思います。
patternUnits / patternContentUnits 属性
patternUnits 属性は pattern 要素の x, y, width, height 属性の座標系を定義する属性で、patternContentUnits 属性は pattern 要素のコンテンツ(内容:パターンに使用する図形要素)の座標系を定義する属性です。
以下は patternUnits 属性にデフォルトの objectBoundingBox を指定して pattern 要素の x, y, width, height 属性の座標系を比率で指定し、patternContentUnits 属性にデフォルトの userSpaceOnUse を指定して pattern 要素の内容の座標系を描画領域の座標で指定する例です。
いずれの属性もデフォルトの値を指定しているので省略しても同じです。
以下の例の場合、パターンを水平および垂直方向に 2 回繰り返したいので、height および width は 0.5 に設定しています(パターンの幅および高さは、ボックス全体のサイズの 0.5 倍 = 半分になります)。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern1" x="0" y="0" width="0.5" height="0.5" patternUnits="objectBoundingBox" patternContentUnits="userSpaceOnUse"> <circle cx="50" cy="50" r="40" fill="url(#my_gradient)"/> </pattern> </defs> <rect fill="url(#pattern1)" x="0" y="0" width="200" height="200"/> </svg>
以下は patternUnits 属性に userSpaceOnUse を指定し、patternContentUnits 属性に objectBoundingBox を指定する例ですが、表示されるパターンは同じ結果になります。
この例の場合もパターンを水平および垂直方向に 2 回繰り返したいので、height および width は 100 に設定しています(パターンの幅および高さは、ボックス全体のサイズ 200 の半分になります)。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern2" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse" patternContentUnits="objectBoundingBox"> <circle cx="0.25" cy="0.25" r="0.2" fill="url(#my_gradient)"/> </pattern> </defs> <rect fill="url(#pattern2)" x="0" y="0" width="200" height="200"/> </svg>
以下は patternUnits 属性と patternContentUnits 属性の両方に objectBoundingBox を指定して同じパターンを作成する例です。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern2-2" x="0" y="0" width="0.5" height="0.5" patternUnits="objectBoundingBox" patternContentUnits="objectBoundingBox"> <circle cx="0.25" cy="0.25" r="0.2" fill="url(#my_gradient)"/> </pattern> </defs> <rect fill="url(#pattern2-2)" x="0" y="0" width="200" height="200"/> </svg>
以下は patternUnits 属性と patternContentUnits 属性の両方に userSpaceOnUse を指定して同じパターンを作成する例です。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern2-3" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse"> <circle cx="50" cy="50" r="40" fill="url(#my_gradient)"/> </pattern> </defs> <rect fill="url(#pattern2-3)" x="0" y="0" width="200" height="200"/> </svg>
パターン動作確認サンプル
以下は patternUnits 属性にデフォルトの objectBoundingBox を、patternContentUnits 属性にデフォルトの userSpaceOnUse を指定して pattern 要素の属性の値を変更して動作を確認するサンプルです。
<svg width="200px" height="200px" viewBox="0 0 200 200" style="border: 1px solid #ccc;"> <defs> <pattern id="pattern4" x="0" y="0" width="0.1" height="0.1" patternUnits="objectBoundingBox" patternContentUnits="userSpaceOnUse"> <circle cx="10" cy="10" r="10" fill="url(#my_gradient)"/> </pattern> </defs> <rect fill="url(#pattern4)" x="0" y="0" width="200" height="200"/> </svg>
width と height でパターンの大きさを決めてから、内容となる circle 要素の半径や座標を変更すると良いかも知れません。
viewBox 属性
以下は viewBox 属性を使ってパターンの描画領域(パターンとして切り出す範囲)を定義する例です。
viewBox 属性が指定されている場合、viewBox 属性でコンテンツの領域を定義するので、patternContentUnits 属性に値を指定してもそれらは無視されるので意味がありません。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern3" x="0" y="0" width="0.5" height="0.5" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="40" fill="url(#my_gradient)"/> </pattern> </defs> <rect fill="url(#pattern3)" x="0" y="0" width="200" height="200"/> </svg>
以下は viewBox 属性を指定して、パターンに4つの図形を使用した例です。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern5" x="0" y="0" width="0.5" height="0.5" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="35" fill="url(#radial_gradient4)"/> <circle cx="70" cy="30" r="20" fill="gold" fill-opacity="0.7"/> <rect x="10" y="10" width="30" height="30" fill="red" fill-opacity="0.5"/> <rect x="40" y="60" width="50" height="30" fill="blue" fill-opacity="0.5"/> </pattern> </defs> <rect fill="url(#pattern5)" x="0" y="0" width="200" height="200"/> </svg>
パターンの中でさらにパターンを参照することができます。以下はパターンの中で別のパターンを参照する例です。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern6" x="0" y="0" width="0.5" height="0.5" viewBox="0 0 100 100"> <!-- パターンを参照 --> <circle cx="50" cy="50" r="50" fill="url(#pattern5)"/> </pattern> </defs> <rect fill="url(#pattern6)" x="0" y="0" width="200" height="200"/> </svg>
stroke に適用
以下は9つの円で構成されたパターンを stroke に適用する例です。
以下の例の場合、パターンを水平および垂直方向に 4 回繰り返したいので、height および width は 0.25 に設定しています。
そして viewBox="0 0 30 30" のパターンの描画領域の中に9つの円でパターンを作成しています。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern7" x="0" y="0" width="0.25" height="0.25" viewBox="0 0 30 30"> <g fill="red"> <circle cx="5" cy="5" r="5"/> <circle cx="15" cy="5" r="5" fill-opacity="0.6"/> <circle cx="25" cy="5" r="5" fill-opacity="0.3"/> </g> <g fill="blue"> <circle cx="5" cy="15" r="5"/> <circle cx="15" cy="15" r="5" fill-opacity="0.6"/> <circle cx="25" cy="15" r="5" fill-opacity="0.3"/> </g> <g fill="gold"> <circle cx="5" cy="25" r="5"/> <circle cx="15" cy="25" r="5" fill-opacity="0.6"/> <circle cx="25" cy="25" r="5" fill-opacity="0.3"/> </g> </pattern> </defs> <rect stroke="url(#pattern7)" stroke-width="100" x="0" y="0" width="200" height="200" fill="mediumpurple" /> </svg>
patternTransform 属性
patternTransform 属性を使うと transform 属性と同様、transform 関数を使用してパターンの変形処理を適用できます。
以下は patternTransform 属性に rotate(45) を指定してパターンを45度回転させる例です。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern8" x="0" y="0" width="0.2" height="0.2" viewBox="0 0 100 100" patternTransform="rotate(45)"> <rect x="10" y="10" width="90" height="90" fill="green"/> <rect x="20" y="20" width="30" height="30" fill="mediumseagreen"/> <rect x="60" y="20" width="30" height="30" fill="darkseagreen"/> <rect x="20" y="60" width="30" height="30" fill="lightseagreen"/> <rect x="60" y="60" width="30" height="30" fill="palegreen"/> </pattern> </defs> <rect fill="url(#pattern8)" x="0" y="0" width="200" height="200"/> </svg>
href(xlink:href)
href(または xlink:href)属性を使うと、別のパターンを参照して利用すことができます(SVG2 では xlink:href は非推奨になっています)。
pattern 要素の属性値の一部や全てを継承し、パターン図形を変えたりすることができます。
以下は前述の例の pattern 要素の属性値をそのまま継承し、パターン図形のみを変える例です。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern9" href="#pattern8"> <rect x="20" y="20" width="80" height="80" fill="url(#my_gradient)"/> </pattern> </defs> <rect fill="url(#pattern9)" x="0" y="0" width="200" height="200"/> </svg>
以下は継承した pattern 要素の width と height 及び viewBox 属性の値を上書きし、パターン図形を変更する例です。
<svg width="200px" height="200px" viewBox="0 0 200 200"> <defs> <pattern id="pattern10" href="#pattern8" width="0.3" height="0.3" viewBox="0 0 120 120"> <rect x="0" y="0" width="100" height="100" fill="palegreen"/> <rect x="10" y="10" width="80" height="80" fill="url(#my_gradient)"/> </pattern> </defs> <rect fill="url(#pattern10)" x="0" y="0" width="200" height="200"/> </svg>
クリッピングとマスキング
SVG はクリッピング(clipping)とマスキング(masking)の機能をサポートしています。
クリッピングは「特定の領域外の描画を抑制します」のように表現されますが、いわゆる「切り抜き」の機能で、設定したパス(領域)の内側のみを表示し、外側を非表示にする(覆い隠す)機能です。半透明効果をかけることはできず、完全に表示するか全く表示しないかになります。
マスキングもクリッピングに似たような機能ですが、透明度や濃淡値を考慮した半透明合成を行います。
clipPath 要素
クリッピングパス(クリッピングする領域)は clipPath 要素で定義します。そしてクリッピングパスを適用する図形要素の clip-path 属性によって参照します。
clipPath 要素自体は直接描画されることはありませんが、通常 defs 要素内で定義します。
clipPath 要素には参照のために使用する id 属性を定義し、以下のような属性を指定することができます。
属性 | 意味 |
---|---|
clipPathUnits | クリッピングパスを定義する要素(clipPath の内容)が参照する座標系を指定します。
|
clip-rule | パスの内側かどうかを判定する方法(fill-rule)。nonzero(デフォルト)または evenodd を指定。 |
属性 | 意味 |
---|---|
clip-path | 適用するクリッピングパスの id を url() で指定(参照)。 |
以下はクリッピングを使って半円を作成する例です。
clipPath 要素内で rect 要素を使って長方形のクリッピング領域を定義します。そして circle 要素に clip-path 属性を指定して定義したクリッピングパスを参照します。
結果として、rect 要素を使って定義した矩形のクリッピング領域の内部(円の上半分)が表示され、それ以外の部分(円のした半分)は非表示になり、半円が作成できます。
<svg width="100" height="100" viewBox="0 0 100 100" style="border:1px dashed #ccc"> <defs> <clipPath id="clip"> <rect x="0" y="0" width="100" height="50" /> </clipPath> </defs> <circle cx="50" cy="50" r="50" clip-path="url(#clip)" fill="red"/> </svg>
以下は画像をハート形にクリッピングする例で、次の画像を使用します。
clipPath 要素内で path 要素を使ってハート形のクリッピング領域を定義して、image 要素の clip-path 属性にクリッピングパスの id を指定してクリッピングしています。
デフォルトでは、クリッピング領域の定義で指定(参照)する座標はクリップングが適用される要素(この場合は image 要素)の座標になります。
<svg width="100" height="100" viewBox="0 0 100 100"> <defs> <clipPath id="heart"> <path d="M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z" /> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#heart)" width="200" height="113"/> </svg>
以下は前述の例同様、画像をハート形にクリッピングする例です。
この例ではまずハート形の path 要素を定義して use 要素を使ってクリッピング領域を定義しています。その際に transform 属性を使って回転や縮小、移動を適用しています。
<svg width="180" height="100" viewBox="0 0 180 100"> <defs> <path id="heart-path" d="M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z" /> <clipPath id="hearts"> <use href="#heart-path"/> <use href="#heart-path" transform="translate(100 20) scale(0.6) rotate(30)"/> <use href="#heart-path" transform="translate(130 30) scale(0.4) rotate(-20)"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#hearts)" width="200" height="113"/> </svg>
以下は3つの円を使ってクリッピングする例です。複数の画像を組み合わせればパスを使わなくても複雑な図形をクリッピングできます。
<svg width="200" height="113" viewBox="0 0 200 113" style="background-color:#90F3BA"> <defs> <clipPath id="circles"> <circle cx="40" cy="40" r="30"/> <circle cx="100" cy="60" r="50"/> <circle cx="160" cy="40" r="30"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#circles)" width="200" height="113"/> </svg>
以下は画像の特定の位置を円形にクリッピングする例です。
<svg width="100" height="100" viewBox="50 10 100 100"> <defs> <clipPath id="clip1"> <circle cx="100" cy="60" r="50"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip1)" width="200" height="113"/> </svg>
この例の場合、200 x 113 の横長の画像のほぼ中心辺りをクリッピングしたいので、svg 要素の viewBox 属性と circle 要素の cx, cy 属性の値を調整しています。
<svg width="200" height="113" viewBox="0 0 200 113"> <image href="../images/sample.jpg" width="200" height="113"/> <!-- クリッピングパスに該当 --> <circle cx="100" cy="60" r="50" fill="transparent" stroke="lightblue"/> <!-- viewBox の範囲 50 10 100 100 に該当 --> <rect x="50" y="10" width="100" height="100" fill="transparent" stroke="gold"/> </svg>
黄色の四角形が viewBox の範囲 50 10 100 100 に該当し、水色の円がクリッピングパスに該当します。
デフォルトではクリッピング領域はクリッピングが適用される要素の座標上で行われます
以下は text 要素を使ってクリッピングする例です。
<svg width="200" height="80" viewBox="0 0 200 80"> <defs> <clipPath id="clip2"> <text x="10" y="70" font-size="70" font-weight="bold">Hello</text> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip2)" width="200" height="113"/> </svg>
以下は text 要素にクリッピングを適用して水平方向中央の位置でテキストの色を変える例です。
rect 要素を使ってクリッピング領域を右側半分に指定しています。
テキストは def 要素内で定義しておいて、use 要素で重ねて描画し、上のレイヤーの文字に対して右半分をクリッピングしています。
<svg width="200" height="100" viewBox="0 0 200 100"> <defs> <clipPath id="clip-border"> <rect width="50%" height="100%"/> </clipPath> <text id="text-border" font-size="30" x="50%" y="65" text-anchor="middle">Blue & Pink</text> </defs> <rect x="0" width="50%" height="100%" fill="blue"/> <rect x="50%" width="50%" height="100%" fill="pink"/> <use href="#text-border" fill="blue"/> <use href="#text-border" fill="pink" clip-path="url(#clip-border)"/> </svg>
クリッピングやマスキングは複数の要素に対しても適用することができます。
以下は defs 要素内で楕円を定義して use 要素で複製したものを g 要素でグループ化した図形にクリップングを適用しています。
<svg viewBox="60 60 120 120"> <defs> <ellipse id="ellipse3" cx="120" cy="120" rx="100" ry="20" fill-opacity="0.3"/> <clipPath id="clip-circle"> <circle cx="120" cy="120" r="60"> </clipPath> </defs> <g clip-path="url(#clip-circle)"> <use href="#ellipse3" x="0" y="0" fill="gray"/> <use href="#ellipse3" x="0" y="0" transform="rotate(30,120,120)" fill="green"/> <use href="#ellipse3" x="0" y="0" transform="rotate(60,120,120)" fill="blue"/> <use href="#ellipse3" x="0" y="0" transform="rotate(90,120,120)" fill="purple"/> <use href="#ellipse3" x="0" y="0" transform="rotate(120,120,120)" fill="red"/> <use href="#ellipse3" x="0" y="0" transform="rotate(150,120,120)" fill="orange"/> </g> </svg>
clipPathUnits 属性
デフォルトでは clipPathUnits 属性の値は userSpaceOnUse で、クリッピング領域の定義はユーザー座標系上(クリッピングが適用される要素の座標上)で行われます
clipPathUnits 属性に objectBoundingBox を指定すると、クリッピングする図形要素のローカルな座標系で定義することができ、値は0〜1の間の相対的な値(比率)で指定します。
以下は clipPathUnits 属性に objectBoundingBox を指定して、クリッピングする図形要素(circle 要素)のローカルな座標系でクリッピングする例です。
<svg width="200" height="113" viewBox="0 0 200 113"> <defs> <clipPath id="clip1x" clipPathUnits="objectBoundingBox"> <circle cx="0.5" cy="0.5" r="0.5"/> </clipPath> </defs> <image href="../images/jquery/sample06.jpg" clip-path="url(#clip1x)" width="200" height="113"/> </svg>
以下のようにクリッピングされます。
以下はクリッピングする図形要素(circle 要素)に transform 属性(移動と縮小)を適用する例です。
clipPathUnits 属性に objectBoundingBox を指定しているので、移動に指定する値も比率で指定する必要があります。
クリッピングする領域を正円に近くなるように scale(0.565,1) としていて、0.565 は 113 ÷ 200 です。
またクリッピング領域の中心を画像の中心に取るように、scale(0.565,1) の前後で translate() を適用しています。
<svg width="200" height="113" viewBox="0 0 200 113"> <defs> <clipPath id="clip1y" clipPathUnits="objectBoundingBox"> <circle cx="0.5" cy="0.5" r="0.5" transform="translate(0.5,0.5),scale(0.565,1),translate(-0.5,-0.5)"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip1y)" width="200" height="113"/> </svg>
以下は viewBox 及び width と height で描画領域とサイズを調整しています。
画像のほぼ中央で幅と高さを 113 になるように、viewBox の min-x を 43.5 にしています。43.5 は (200-113)/2 です。
<svg width="113" height="113" viewBox="43.5 0 113 113" > <defs> <clipPath id="clip1y2" clipPathUnits="objectBoundingBox"> <circle cx="0.5" cy="0.5" r="0.5" transform="translate(0.5,0.5),scale(0.565,1),translate(-0.5,-0.5)"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip1y2)" width="200" height="113"/> </svg>
clipPathUnits 属性に objectBoundingBox を指定して path 要素で三角形のクリッピング領域を作成する例です。path 要素に指定する値は比率を指定します。
<svg width="200" height="113" viewBox="0 0 200 113"> <defs> <clipPath id="clip1z" clipPathUnits="objectBoundingBox"> <path d="M0,1 H1 L0.5,0 z"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip1z)" width="200" height="113"/> </svg>
SVG path ジェネレーターの利用
クリッピング領域を作成するパスは基本図形要素や path 要素で作成したり、フリー素材や Illustrator などを利用する方法の他に、SVG path ジェネレーターを利用することもできます。
以下のサイトにいくつかの SVG path ジェネレーターが紹介されています。
Tools to Visualize and Edit SVG Paths (Kinda!)
Clippy は CSS clip-path 用のジェネレーターで SVG path ジェネレーターではありませんが、使い勝手がとてもよく、生成される CSS の clip-path: polygon() の値を SVG パスに利用することもできます(値を変換する手間がかかりますが)。
使用する画像の URL を指定して、実際の画像でも確認することができます。
以下は吹き出しのシェイプを選択して、生成されたコードの百分率の値を100分の1にして0〜1の間の数値の比率に変更して利用する例です。
ジェネレーターのページでは Demo Size に実際の画像のサイズ(この例では 200 x 113)を指定して、ポイントの位置を移動させるなどして形状を確認することができます。
<!-- 生成された CSS clip-path のコード --> clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%); <!-- 上記を SVG polygon に変換(値を100分の1にして%を削除) --> <polygon points="0 0, 1 0, 1 0.75, 0.75 0.75, 0.75 1, 0.50 0.75, 0 0.75"/>
<svg width="200" height="113" viewBox="0 0 200 113"> <defs> <clipPath id="clipX" clipPathUnits="objectBoundingBox"> <polygon points="0 0, 1 0, 1 0.75, 0.75 0.75, 0.75 1, 0.50 0.75, 0 0.75"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clipX)" width="200" height="113"/> </svg>
絶対パスから相対パスへの変換
相対パスで指定すれば、いろいろなサイズに対応できるので場合によっては便利ですが、絶対的な座標(userSpaceOnUse)で指定した path を相対的なパス(objectBoundingBox)に変換するのは大変です。
以下のサイトを利用すれば簡単に絶対パスを相対パスへの変換することができます。
Convert SVG absolute clip-path to relative
上記サイトにアクセスすると、以下のような画面になるので変換したいパスを「Insert clip-path coordinates for userSpaceOnUse:」にペーストすると自動的に変換されたパスが「Take clip-path coordinates for objectBoundingBox:」に出力されます。「Remove offset」にチェックを入れればオフセット値を削除します。
パスによってはうまく変換されない場合もあるので、「Live Demos」で変換結果のパスの表示を確認することができます。
また、アイコンのボタンをクリックするとそのアイコンの相対パスが出力されるので、そのまま利用することもできます。
以下は上記サイトの「ホーム」のアイコンを選択して出力されたパスを使った例です。
<svg width="200" height="113" viewBox="0 0 200 113"> <defs> <clipPath id="clip-cpu1" clipPathUnits="objectBoundingBox"> <path d="M1,0.636 l-0.5,-0.428,-0.5,0.428 v-0.174 l0.5,-0.428,0.5,0.428 M0.875,0.62 v0.413 h-0.25 v-0.276 h-0.25 v0.276 h-0.25 v-0.413 l0.375,-0.31"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip-cpu1)" width="200" height="113"/> </svg>
この例の場合、クリッピングを適用する画像が横長なので以下のような表示になります。
以下はホームのアイコンのパスを変形の基準点を中央にずらしてからX軸方向に 0.565 倍(画像の高さの113を幅の200で割った値)し、元の位置に戻しています(関連:scale)。
また、先の円の例と同様 viewBox 及び width と height で描画領域とサイズを調整しています。
<svg width="113" height="113" viewBox="43.5 0 113 113"> <defs> <clipPath id="clip-cpu1x" clipPathUnits="objectBoundingBox"> <path d="M1,0.636 l-0.5,-0.428,-0.5,0.428 v-0.174 l0.5,-0.428,0.5,0.428 M0.875,0.62 v0.413 h-0.25 v-0.276 h-0.25 v0.276 h-0.25 v-0.413 l0.375,-0.31" transform="translate(0.5,0.5),scale(0.565,1),translate(-0.5,-0.5)"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip-cpu1x)" width="200" height="113"/> </svg>
以下は前述の例と同様、ホームのアイコンのパスに transform を適用しています。また、星型のパスも同様に transform を適用し、その位置を中央に戻すのではなく左上に移動して更に縮小しています。
変形を使うのではなく、使用する画像の縦横比を変えるという方法もあるかと思います。
<svg width="200" height="113" viewBox="0 0 200 113" > <defs> <clipPath id="clip-cpu2" clipPathUnits="objectBoundingBox"> <!-- ホームのパス --> <path d="M1,0.636 l-0.5,-0.428,-0.5,0.428 v-0.174 l0.5,-0.428,0.5,0.428 M0.875,0.62 v0.413 h-0.25 v-0.276 h-0.25 v0.276 h-0.25 v-0.413 l0.375,-0.31" transform="translate(0.5,0.5),scale(0.565,1),translate(-0.5,-0.5)"/> <!-- 星型のパス --> <path d="M0.5,0.846 l-0.309,0.154,0.044,-0.357 L0,0.382 l0.336,-0.067 L0.5,0 l0.164,0.315,0.336,0.067,-0.235,0.261,0.044,0.357" transform="scale(0.3),translate(0.4,0.9),scale(0.565,1),translate(-0.5,-0.5)"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip-cpu2)" width="200" height="113"/> </svg>
以下は SVG のフリー素材を絶対パスから相対パスへ変換してクリッピング領域を作成する例です。
この場合も、縮小及び移動を適用しています。
<svg width="200" height="113" viewBox="0 0 200 113"> <defs> <clipPath id="clip-cpu3" clipPathUnits="objectBoundingBox"> <!-- ゾウのフリー素材のパスを絶対パスから相対パスへの変換して指定 --> <path d="M0.805,0 H0.407 C0.278,0,0.173,0.132,0.173,0.295 V0.362 V0.631 C0.173,0.652,0.173,0.673,0.173,0.694 C0.173,0.738,0.164,0.793,0.122,0.814 C0.102,0.825,0.08,0.812,0.063,0.796 L0,0.891 C0.085,0.97,0.182,0.973,0.25,0.892 C0.309,0.821,0.314,0.729,0.314,0.634 C0.336,0.643,0.353,0.669,0.353,0.7 V1 H0.441 H0.517 V0.793 H0.819 V1 H1 V0.246 C1,0.11,0.913,0,0.805,0 M0.344,0.408 C0.323,0.408,0.305,0.386,0.305,0.36 C0.305,0.333,0.323,0.311,0.344,0.311 C0.365,0.311,0.383,0.333,0.383,0.36 C0.383,0.386,0.365,0.408,0.344,0.408 M0.467,0.646 C0.46,0.646,0.454,0.638,0.454,0.628 C0.454,0.619,0.46,0.611,0.467,0.611 C0.524,0.611,0.576,0.582,0.613,0.535 C0.65,0.488,0.673,0.423,0.673,0.351 C0.673,0.341,0.679,0.334,0.687,0.334 C0.695,0.334,0.701,0.341,0.701,0.351 C0.701,0.514,0.596,0.646,0.467,0.646" transform="translate(0.65,0.5),scale(0.565,1),translate(-0.5,-0.5)"/> <!-- バナナのフリー素材のパスを絶対パスから相対パスへの変換して指定 --> <path d="M0.91,0.24 V0.072 l0.081,-0.003 V0.003 H0.737 v0.069 h0.085 c0,0,0.014,0.066,0,0.146 c-0.037,0.203,-0.275,0.437,-0.531,0.502 c-0.136,0.034,-0.239,0.026,-0.239,0.026 c-0.02,-0.005,-0.04,0.005,-0.048,0.024 c-0.008,0.019,-0.001,0.041,0.01,0.067 c0,0,0.048,0.134,0.293,0.161 c0.323,0.035,0.585,-0.106,0.675,-0.42 C1,0.384,0.957,0.24,0.91,0.24 M0.601,0.81 c-0.12,0.067,-0.249,0.095,-0.348,0.096 l0,-0.038 c0.093,-0.001,0.217,-0.028,0.33,-0.091 c0.114,-0.063,0.217,-0.163,0.272,-0.309 l0.035,0.013 C0.831,0.637,0.72,0.743,0.601,0.81" transform="scale(0.4),translate(0.35,0.9),scale(0.565,1),translate(-0.5,-0.5)"/> </clipPath> </defs> <image href="../images/sample.jpg" clip-path="url(#clip-cpu3)" width="200" height="113"/> </svg>
clip-rule 属性
clip-rule 属性は clipPath 要素に含まれる path などのグラフィックス要素に対して適用されるパスの内側かどうかを判定するルールです。
以下は fill-rule により異なる描画になるパスに対して clip-rule 属性に evenodd を指定した場合の例です。
<svg width="300" height="150" viewBox="0 0 600 300"> <defs> <clipPath id="clip3" clip-rule="evenodd"> <path d="M 150,35 L223,261 L31,121 L269,121 L77,261 L150,35 z"/> <path d="M 450,35 L523,261 L331,121 L569,121 L377,261 L450 35 L569,121 L523,261 L377,261 L331,121z"/> </clipPath> </defs> <image x="0" y="0" href="../images/sample2.jpg" clip-path="url(#clip3)" width="600" height="400"/> </svg>
以下は前述の例と同じパスに対してデフォルトの nonzero を指定した場合の例です。
<svg width="300" height="150" viewBox="0 0 600 300"> <defs> <clipPath id="clip3x" clip-rule="nonzero"> <path d="M 150,35 L223,261 L31,121 L269,121 L77,261 L150,35 z"/> <path d="M 450,35 L523,261 L331,121 L569,121 L377,261 L450 35 L569,121 L523,261 L377,261 L331,121z"/> </clipPath> </defs> <image x="0" y="0" href="../images/sample2.jpg" clip-path="url(#clip3x)" width="600" height="400"/> </svg>
mask 要素
マスキングもクリッピングと使い方は似ていて、マスクする領域を mask 要素で定義し、マスクを適用する図形要素の mask 属性によって参照します。
クリッピングとは異なり、マスク領域の定義では fill や fill-opacity で表示・非表示や透明度を指定します。
マスク領域の図形の塗り(fill)が白の場合は、その部分は完全に表示されてクリッピングと同じ結果になります。塗りが黒の場合は、その部分は覆い隠され非表示になります(fill の初期値は black なので fill を指定しない図形は非表示になります)。
マスクの透明度(アルファ値)は「R*0.2125 + G*0.7154 + B*0.0721」という式を使って変換され、合成された画像の RGB の値により異なってくるようですが、白で表示、黒で非表示、中間の透明度は塗りを白にして fill-opacity で制御することができます。
以下は画像にマスクを適用する例で、次の画像を使用しています。
以下では mask 要素を使って3つの円(circle 要素)からなるマスク領域を定義し、それぞれに白(white)、グレー(gray)、黒に近いグレー(#222)の塗りを指定しています。
定義した mask 要素には id を付与し、マスクが適用される image 要素に mask 属性を設定して、マスクの id を url() で指定して参照します。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="circles-mask1"> <circle cx="50" cy="85" r="50" fill="white"/> <circle cx="150" cy="85" r="50" fill="gray"/> <circle cx="250" cy="85" r="50" fill="#222"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#circles-mask1)" width="300" height="170"/> </svg>
以下では、全てのマスク図形の fill に white を指定してそれぞれ異なる値の fill-opacity を指定しています。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="circles-mask2"> <circle cx="50" cy="85" r="50" fill="white" fill-opacity="1"/> <circle cx="150" cy="85" r="50" fill="white" fill-opacity="0.5"/> <circle cx="250" cy="85" r="50" fill="white" fill-opacity="0.2"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#circles-mask2)" width="300" height="170"/> </svg>
以下は全てのマスク図形の fill-opacity の値を 0.6 にして部分的に重なるように配置しています。そしてその下のレイヤーにopacity を 0.4 に指定した同じ画像を配置して重ねています。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <image id="bg-jpg" href="../images/jquery/sample06.jpg" width="300" height="170"/> <mask id="circles-mask3"> <circle cx="70" cy="85" r="70" fill="white" fill-opacity="0.6"/> <circle cx="150" cy="85" r="70" fill="white" fill-opacity="0.6"/> <circle cx="230" cy="85" r="70" fill="white" fill-opacity="0.6"/> </mask> </defs> <use href="#bg-jpg" opacity="0.4"/> <use href="#bg-jpg" mask="url(#circles-mask3)"/> </svg>
以下は始点(0%)の不透明度が1で終点(100%)の不透明度が0の白一色の線形グラデーションを定義してマスク図形の rect 要素に適用する例です。マスク図形の rect 要素はマスクを適用する image 要素と同じ大きさにしています。
始点(0%)では image 要素は完全に表示され、徐々に不透明になり終点(100%)では非表示になっています。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <linearGradient id="white-gradient"> <stop offset="0%" stop-color="white" stop-opacity="1" /> <stop offset="100%" stop-color="white" stop-opacity="0" /> </linearGradient> <mask id="gradient-mask"> <rect x="0" y="0" width="300" height="170" fill="url(#white-gradient)" /> </mask> </defs> <image href="../images/sample.jpg" mask="url(#gradient-mask)" width="300" height="170"/> </svg>
以下は白の線形グラデーションを適用したマスクを使って2色のグラデーションを描画する例です。
以下の例では stop 要素の offset に 10% と 90% を指定しています。
2つの rect 要素を重ねて描画し、上のレイヤーの rect 要素(オレンジ色)にはグラデーションを適用したマスクを指定しているので、右側に行くほど透明になり下の緑色の rect 要素が透けて見え、90% の位置で完全に透明になるのでそれ以降は完全な緑色になっています。
<svg width="200" height="100" viewBox="0 0 200 100"> <defs> <linearGradient id="white-gradient2"> <stop offset="10%" stop-color="white" stop-opacity="1" /> <stop offset="90%" stop-color="white" stop-opacity="0" /> </linearGradient> <mask id="gradient-mask2"> <rect x="0" y="0" width="200" height="100" fill="url(#white-gradient2)" /> </mask> </defs> <rect x="0" y="0" width="200" height="100" fill="green"/> <rect x="0" y="0" width="200" height="100" fill="orange" mask="url(#gradient-mask2)"/> </svg>
以下は images 要素の上に rect 要素を重ねて両方にグラデーションを使ったマスクを適用する例です。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <linearGradient id="white-gradient3" x1="0%" y1="0%" x2="0%" y2="100%"> <stop offset="0%" stop-color="white" stop-opacity="1" /> <stop offset="100%" stop-color="white" stop-opacity="0.1" /> </linearGradient> <mask id="gradient-mask3"> <rect x="0" y="0" width="300" height="170" fill="url(#white-gradient3)" /> </mask> </defs> <image href="../images/jquery/sample06.jpg" mask="url(#gradient-mask3)" width="300" height="170"/> <rect x="0" y="0" width="300" height="170" fill="blue" fill-opacity="0.5" mask="url(#gradient-mask3)"/> </svg>
マスク領域全体の塗りを白(または黒以外)にして、塗りの黒の図形を配置するとその部分が非表示になり、クリッピング領域を反転させたようになります。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="circles-cut-mask"> <rect x="0" y="0" width="300" height="170" fill="white"/> <circle cx="150" cy="85" r="30"/> </mask> </defs> <image href="../images/jquery/sample06.jpg" mask="url(#circles-cut-mask)" width="300" height="170"/> </svg>
塗りの黒の図形上に塗りの白などの図形を重ねればその部分が表示されます。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="circles-cut-mask2"> <rect x="0" y="0" width="300" height="170" fill="white"/> <circle cx="150" cy="85" r="60"/> <circle cx="90" cy="45" r="25"/> <circle cx="210" cy="45" r="25"/> <circle cx="130" cy="65" r="15" fill="white" fill-opacity="0.3"/> <circle cx="130" cy="70" r="10" fill="white"/> <circle cx="170" cy="65" r="15" fill="white" fill-opacity="0.3"/> <circle cx="170" cy="70" r="10" fill="white"/> <ellipse cx="150" cy="115" rx="30" ry="20" fill="white"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#circles-cut-mask2)" width="300" height="170"/> </svg>
以下は rect 要素にグラデーションを使った矩形のマスクを適用したテキストの例です。
マスク図形の rect 要素には始点の不透明度が1で終点の不透明度が0の白一色の線形グラデーションを適用しています。このマスクをオレンジ色のテキストに適用すると、始点は不透明で右側に行くほど透明になりオレンジ色が透けて見え、塗りが透明からオレンジ色へのグラデーションになります。
そしてテキストの塗りを transparent にした同じテキストを重ねてストロークのみを指定しています。
<svg width="300" height="60" viewBox="0 0 300 60"> <defs> <linearGradient id="white-gradient4" > <stop offset="0" stop-color="white" stop-opacity="0" /> <stop offset="1" stop-color="white" stop-opacity="1" /> </linearGradient> <mask id="gradient-mask4"> <!-- rect 要素にグラデーションを適用した矩形のマスク図形 --> <rect x="0" y="0" width="300" height="60" fill="url(#white-gradient4)" /> </mask> <text id="text-hello" x="50%" y="50" font-size="40" font-family="Arial Black" text-anchor="middle" > Hello World ! </text> </defs> <!-- 薄緑色の背景を指定した矩形の描画 --> <rect x="0" y="0" width="100%" height="100%" fill="#E5FAD2" stroke="darkseagreen"/> <!-- 同じテキストを二度描画して重ねる。最初のテキストは塗りをオレンジにしてマスクを適用 --> <use href="#text-hello" fill="orange" mask="url(#gradient-mask4)" /> <!-- 二番目のテキストはストロークのみで塗りはなし、マスクは適用しない --> <use href="#text-hello" fill="transparent" stroke="#999" stroke-width="1" /> </svg>
以下は二つの図形を互いにマスクすることで共通部を切り抜く例です。
マスクの下地用に塗りを白にした矩形とテキスト及び円を定義し、テキストと円の図形のマスクを定義します。これにより白地の矩形部分が表示され、マスク図形の部分が非表示になります。
黒(#333)の塗りの矩形を描画し、その上にオレンジ色のテキストと円を描画し、テキストには円の図形のマスクを、円にはテキストのマスクを適用します。
テキストは円の図形でマスクされるのでその部分が透けて黒になり、円はテキストの図形でマスクされるのでその部分が透けて黒になります。
<svg width="300" height="200" viewBox="0 0 300 200"> <defs> <rect id="rect-white" width="100%" height="100%" fill="white"/> <text id="text-jazz" x="50%" y="65%" font-size="80" text-anchor="middle">Jazz</text> <circle id="circle-bottom" cx="50%" cy="450" r="350"/> <mask id="text-mask"> <use href="#rect-white"/> <use href="#text-jazz"/> </mask> <mask id="circle-mask"> <use href="#rect-white"/> <use href="#circle-bottom"/> </mask> </defs> <rect width="100%" height="100%" fill="#333"/> <g fill="orange"> <use href="#text-jazz" mask="url(#circle-mask)"/> <use href="#circle-bottom" mask="url(#text-mask)"/> </g> </svg>
以下は上記と同じことをクリッピングで行う例です。
<svg width="300" height="200" viewBox="0 0 300 200"> <defs> <circle id="circle-bottom2" cx="50%" cy="450" r="350"/> <clipPath id="clip-circle-bottom2"> <use href="#circle-bottom2"/> </clipPath> <text id="text-jazz2" x="50%" y="65%" font-size="80" text-anchor="middle">Jazz</text> </defs> <rect width="100%" height="100%" fill="#333"/> <g fill="orange"> <use href="#circle-bottom2"/> <use href="#text-jazz2"/> </g> <use href="#text-jazz2" fill="#333" clip-path="url(#clip-circle-bottom2)" /> </svg>
mask 要素には以下のような属性を指定することができます。
属性 | 意味 |
---|---|
maskUnits | mask 要素の x, y, width, height 属性の座標系を定義する属性で以下を指定できます。
|
maskContentUnits | mask 要素のコンテンツ(内容:マスクに使用する図形要素)の座標系を定義する属性で以下を指定できます。
|
x | マスク領域の左上の X 座標。初期値:-10% |
y | マスク領域の左上の Y 座標。初期値:-10% |
width | マスク領域の幅。値を 0 にすると要素は描画されません。初期値:120% |
height | マスク領域の高さ。値を 0 にすると要素は描画されません。初期値:120% |
maskUnits 属性
pattern 要素同様、mask 要素の x, y, width, height 属性に指定する値は、maskUnits 属性の値により比率で指定するかマスクを適用する要素の座標で指定するかを選択できます。
今までの例では全てデフォルトでの指定で、以下のように mask 要素の x, y, width, height 属性は省略して初期値(x="-10%" y="-10%" width="120%" height="120%")を使用していました。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="circles-mask4"> <circle cx="80" cy="85" r="80" fill="white" fill-opacity="0.7"/> <circle cx="150" cy="85" r="80" fill="white" fill-opacity="0.7"/> <circle cx="220" cy="85" r="80" fill="white" fill-opacity="0.7"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#circles-mask4)" width="300" height="170"/> </svg>
以下は maskUnits 属性に objectBoundingBox を指定して x, y, width, height 属性を比率で指定する例です。以下ではパーセントで指定していますが、x="0.05" y="0.05" width="0.9" height="0.9" のように0〜1の間の数値で指定することもできます。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="circles-mask5" maskUnits="objectBoundingBox" x="5%" y="5%" width="90%" height="90%" > <circle cx="80" cy="85" r="80" fill="white" fill-opacity="0.7"/> <circle cx="150" cy="85" r="80" fill="white" fill-opacity="0.7"/> <circle cx="220" cy="85" r="80" fill="white" fill-opacity="0.7"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#circles-mask5)" width="300" height="170"/> </svg>
以下は上記と同じことを maskUnits 属性に userSpaceOnUse を指定して、マスクを適用する要素(mask 属性で mask 要素を参照している要素。この場合は image 要素)の座標で指定する例です。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="circles-mask6" maskUnits="userSpaceOnUse" x="15" y="8.5" width="270" height="153" > <circle cx="80" cy="85" r="80" fill="white" fill-opacity="0.7"/> <circle cx="150" cy="85" r="80" fill="white" fill-opacity="0.7"/> <circle cx="220" cy="85" r="80" fill="white" fill-opacity="0.7"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#circles-mask6)" width="300" height="170"/> </svg>
maskContentUnits 属性
clipPath 要素の clipPathUnits 属性同様、mask 要素の内容(マスクに使用する図形要素)に指定する値も maskContentUnits 属性の値により比率で指定するかマスクを適用する要素の座標で指定するか選択できます。
以下は maskContentUnits 属性に objectBoundingBox を指定して、マスク領域(マスクをかける要素)の座標を比率で指定する例です。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="mix-mask" maskContentUnits="objectBoundingBox"> <circle cx="0.5" cy="0.5" r="0.3" fill="white" fill-opacity="0.5"/> <path d="M0,1 H1 L0.5,0 z" fill="white" fill-opacity="0.5"/> <rect x="0.4" y="0.45" width="0.2" height="0.2" fill="white"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#mix-mask)" width="300" height="170"/> </svg>
以下は同じ比率のマスクを重ねる例です。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <mask id="rect-mask" maskContentUnits="objectBoundingBox"> <g fill="white"> <rect x="0" y="0" width="1" height="1" fill-opacity="0.2"/> <rect x="0.2" y="0.2" width="0.6" height="0.6" fill-opacity="0.4"/> <rect x="0.4" y="0.4" width="0.4" height="0.4" fill-opacity="0.6"/> <rect x="0.6" y="0.6" width="0.2" height="0.2"/> </g> </mask> </defs> <image href="../images/sample.jpg" mask="url(#rect-mask)" width="300" height="170"/> </svg>
同じ比率のマスクを重ねる場合、以下のように defs 要素内で元の図形を定義して use 要素で複製し transform 属性の scale() を使っても簡単です。
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <rect id="rectx" x="0" y="0" width="1" height="1" fill="white"/> <mask id="rect-mask2" maskContentUnits="objectBoundingBox"> <use href="#rectx" fill-opacity="0.2"/> <use href="#rectx" fill-opacity="0.4" transform="translate(0.5,0.5),scale(0.8),translate(-0.5,-0.5)"/> <use href="#rectx" fill-opacity="0.6" transform="translate(0.5,0.5),scale(0.6),translate(-0.5,-0.5)"/> <use href="#rectx" fill-opacity="0.8" transform="translate(0.5,0.5),scale(0.4),translate(-0.5,-0.5)"/> <use href="#rectx" transform="translate(0.5,0.5),scale(0.2),translate(-0.5,-0.5)"/> </mask> </defs> <image href="../images//sample.jpg" mask="url(#rect-mask2)" width="300" height="170"/> </svg>
以下はホームアイコンのパスにグラデーションを適用したマスクの例です。viewBox 及び width と height で描画領域とサイズを調整しています。
<svg width="170" height="170" viewBox="65 0 170 170"> <defs> <linearGradient id="white-gradient5" x1="0" y1="0" x2="0" y2="1"> <stop offset="0" stop-color="white" stop-opacity="0.3" /> <stop offset="0.5" stop-color="white" stop-opacity="1" /> <stop offset="1" stop-color="white" stop-opacity="0" /> </linearGradient> <mask id="home-mask" maskContentUnits="objectBoundingBox"> <path d="M1,0.636 l-0.5,-0.428,-0.5,0.428 v-0.174 l0.5,-0.428,0.5,0.428 M0.875,0.62 v0.413 h-0.25 v-0.276 h-0.25 v0.276 h-0.25 v-0.413 l0.375,-0.31" transform="translate(0.5,0.5),scale(0.565,1),translate(-0.5,-0.5)" fill="url(#white-gradient5)"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#home-mask)" width="300" height="170"/> </svg>
関連項目:絶対パスから相対パスへの変換
以下は Clippy を使って生成したX印のパスをマスクに適用する例です。
但し、Clippy は CSS clip-path 用のジェネレーターなので生成されたコードの値を変換しています。
関連項目:SVG path ジェネレーターの利用
<!-- 生成された CSS clip-path のコード --> clip-path: polygon(20% 0%, 0% 20%, 30% 50%, 0% 80%, 20% 100%, 50% 70%, 80% 100%, 100% 80%, 70% 50%, 100% 20%, 80% 0%, 50% 30%); <!-- 上記を SVG polygon に変換(値を100分の1にして%を削除) し fill 属性を追加--> <polygon points="0.20 0, 0 0.20, 0.30 0.50, 0 0.80, 0.20 1, 0.50 0.70, 0.80 1, 1 0.80, 0.70 0.50, 1 0.20, 0.80 0, 0.50 0.30" fill="url(#white-gradient6)"/>
<svg width="300" height="170" viewBox="0 0 300 170"> <defs> <linearGradient id="white-gradient6"> <stop offset="0" stop-color="white" stop-opacity="0" /> <stop offset="0.5" stop-color="white" stop-opacity="1" /> <stop offset="1" stop-color="white" stop-opacity="0" /> </linearGradient> <mask id="x-mask" maskContentUnits="objectBoundingBox"> <polygon points="0.20 0, 0 0.20, 0.30 0.50, 0 0.80, 0.20 1, 0.50 0.70, 0.80 1, 1 0.80, 0.70 0.50, 1 0.20, 0.80 0, 0.50 0.30" fill="url(#white-gradient6)"/> </mask> </defs> <image href="../images/sample.jpg" mask="url(#x-mask)" width="300" height="170"/> </svg>
画像(img 要素)に SVG を重ねる
image 要素を使えば SVG に画像を取り込めますが、以下は HTML の img 要素に SVG を重ねて図形やテキストを描画する例です。
img 要素と svg 要素を div 要素でラップして、svg 要素を絶対配置にして img 要素の上に重ねます。
レスポンシブにするために、svg 要素には width と height は指定せず、CSS で親要素の div 要素に max-width を指定しています。
img 要素は width を 100% にして、親要素の大きさに追随させます。
SVG では viewBox 属性で指定した描画領域の座標を使って図形やテキストを配置しています(circle 要素はパーセントで指定していますが)。
<div class="svg-over-div"> <img class="clip-path-sample" src="images/cp-01.jpg" alt=""> <svg viewBox="0 0 300 225"> <defs> <marker id="auto-arrow-gray" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" fill="#999" orient="auto-start-reverse"> <path d="M 0 0 L 10 5 L 0 10 z" /> </marker> </defs> <circle cx="50%" cy="50%" r="3"/> <text class="blue" x="120" y="126" font-size="10">(50%, 50%)</text> <line x1="3" y1="112.5" x2="57" y2="112.5" marker-start="url(#auto-arrow-gray)" marker-end="url(#auto-arrow-gray)"/> <text x="17" y="130" font-size="10">60px</text> <line x1="243" y1="112.5" x2="297" y2="112.5" marker-start="url(#auto-arrow-gray)" marker-end="url(#auto-arrow-gray)"/> <text x="257" y="130" font-size="10">60px</text> <line x1="150" y1="3" x2="150" y2="42" marker-start="url(#auto-arrow-gray)" marker-end="url(#auto-arrow-gray)"/> <text x="160" y="28" font-size="10">45px</text> <line x1="150" y1="182" x2="150" y2="222" marker-start="url(#auto-arrow-gray)" marker-end="url(#auto-arrow-gray)"/> <text x="160" y="215" font-size="10">45px</text> </svg> </div>
img 要素と svg 要素をラップする div 要素(.svg-over-div)には絶対配置する svg 要素の基準となるように position: relative; を指定し、svg 要素には position: absolute; と top: 0; 及び left: 0; を設定します。
line や text 要素、marker の色は CSS で設定しています。
この例では img 要素には CSS で clip-path を指定してクリッピングしています。
.svg-over-div { position: relative; /* svg 要素の基準とする */ max-width: 300px; border: 1px solid #ccc; } .svg-over-div img { width: 100%; } .clip-path-sample { clip-path: inset(20% round 10px 20px 30px 50px); } .svg-over-div svg { position: absolute; /* 絶対配置にして img 要素に重ねる */ top: 0; left: 0; overflow: visible; } .svg-over-div svg line { stroke: gold; } .svg-over-div svg text { fill: orange; } .svg-over-div svg text.blue { fill:blue; } .svg-over-div svg circle { fill: red; } #auto-arrow-gray { fill: orange; /* マーカーの色を上書き */ }
以下は CSS でクリッピングした画像(img 要素)の背景に元の(クリッピングする前の)画像を配置して重ねる例です。
背景に追加する画像(img 要素)は svg 要素と同様に絶対配置にしています。
追加した背景の画像には不透明度(opacity)を指定しています。
<div class="svg-over-div"> <img class="bg" src="images/cp-01.jpg" alt=""><!-- 背景に画像を追加 --> <img class="clip-path-sample" src="images/cp-01.jpg" alt=""> <svg class="fg" viewBox="0 0 300 225"> <circle cx="50%" cy="50%" r="3"/> <text class="blue" x="120" y="126" font-size="10">(50%, 50%)</text> <line x1="3" y1="112.5" x2="57" y2="112.5" marker-start="url(#auto-arrow-gray)" marker-end="url(#auto-arrow-gray)"/> <text x="17" y="130" font-size="10">60px</text> <line x1="243" y1="112.5" x2="297" y2="112.5" marker-start="url(#auto-arrow-gray)" marker-end="url(#auto-arrow-gray)"/> <text x="257" y="130" font-size="10">60px</text> <line x1="150" y1="3" x2="150" y2="42" marker-start="url(#auto-arrow-gray)" marker-end="url(#auto-arrow-gray)"/> <text x="160" y="28" font-size="10">45px</text> <line x1="150" y1="182" x2="150" y2="222" marker-start="url(#auto-arrow-gray)" marker-end="url(#auto-arrow-gray)"/> <text x="160" y="215" font-size="10">45px</text> </svg> </div>
svg 要素にはクラスを追加して、line や text 要素の色を変更しています。
.svg-over-div img.bg { width: 100%; position: absolute; /* 絶対配置にして重ねる */ top: 0; left: 0; opacity: 0.5; /* 不透明度を指定 */ } .svg-over-div svg.fg line { stroke: white; } .svg-over-div svg.fg text { fill: white; } .svg-over-div svg.fg text.blue { fill: blue; }
CSS で svg 要素を表示
CSS の疑似要素(::before ::after)を使って svg 要素を表示したり、アニメーション適用する方法や svg 要素を背景パターンに使用する例です。
疑似要素(::before ::after)を使って表示
以下は Bootstrap Icons の封筒のアイコンの SVG です。
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope" viewBox="0 0 16 16"> <path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z"/> </svg>
HTML にインラインで上記を記述すると以下のような幅 16px、高さ 16px のアイコンが表示されます。
この場合、fill 属性は currentColor キーワードが設定されているので親の要素の色で表示されますが、疑似要素で表示する場合は currentColor キーワードは効かないようで、色を指定するには fill 属性で指定します。
CSS の疑似要素(::before ::after)を使って表示する場合、content または、background-image の値に url() 関数でデータ URL スキームを使って URI エンコードした svg のコードを指定します。
データ URL
データ URL は data: スキームが先頭についた URL で、小さなファイルをインラインで文書に埋め込むことができます。
データ URL の構文は以下のようになっていて、接頭辞の data:、データの種類を示す MIME タイプの <mediatype>、オプションの base64 トークン、データ自体の <data> で構成されます。
data: <mediatype> [;base64],<data>
svg 要素を埋め込む場合は、以下のようになります。
image/svg+xml が SVG の MIME タイプ(<mediatype>)になります。また、svg のマークアップは URI エンコードします。
data:image/svg+xml, URI エンコードした svg のマークアップ
上記を url() 関数に指定します。
url("data:image/svg+xml, URI エンコードした svg のマークアップ")
URI エンコード
svg のマークアップの URI(URL)エンコードは、 JavaScript の関数 encodeURIComponent() で変換することができますが、スペースなどもエンコードされてしまいサイズが大きくなります。
例えば、前述の封筒のアイコンの SVG を encodeURIComponent() で変換すると以下のようになります。
%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22currentColor%22%20class%3D%22bi%20bi-envelope%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M0%204a2%202%200%200%201%202-2h12a2%202%200%200%201%202%202v8a2%202%200%200%201-2%202H2a2%202%200%200%201-2-2V4zm2-1a1%201%200%200%200-1%201v.217l7%204.2%207-4.2V4a1%201%200%200%200-1-1H2zm13%202.383l-4.758%202.855L15%2011.114v-5.73zm-.034%206.878L9.271%208.82%208%209.583%206.728%208.82l-5.694%203.44A1%201%200%200%200%202%2013h12a1%201%200%200%200%20.966-.739zM1%2011.114l4.758-2.876L1%205.383v5.73z%22%2F%3E%3C%2Fsvg%3E
関連ページ:URI エンコード変換ツール
データ URL では ' のみが許可されているのようなので、SVG コードのダブルクォート(")をシングルクォート(')に交換して「<」と「>」、及び「#」をエンコードすれば良いようです。
また、url() 関数で指定する値はシングルまたはダブルクォートで囲むか、引用符を省略することも可能ですが、この場合は SVG コードの属性はシングルクォートで囲むので、値全体をダブルクォートで囲みます。
参考サイト:Optimizing SVGs in data URIs
前述の封筒のアイコンの SVG を この方法でエンコードすると以下のようになります。
この例では Bootstrap Icons で設定されている class 属性はそのまま残してありますが、削除することもできます。
また、fill 属性も currentColor のままにしてありますが、必要に応じて色を指定することができます。
※ その際に fill 属性に RGB 16進数(例 #ffffff)で指定する場合は「#」を「%23」に変換する必要があります(例:%23ffffff)。
%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-envelope' viewBox='0 0 16 16'%3E%3Cpath d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z'/%3E%3C/svg%3E
以下のページのツールを使えば、上記のように <、>、# 文字をそれぞれ %3C、%3E、%23 にパーセントエンコード変換し、ダブルクオート(")はシングルクォート(')に変換します。また、改行は削除します。
関連ページ:SVG エスケープツール(SVG URL Encoder)
content プロパティに指定する例
以下は疑似要素 ::before を使って、前述の封筒のアイコンの svg を content プロパティに指定して表示する例です。
content に svg を指定する場合、疑似要素の CSS の width と height では svg 画像の幅と高さを変更することはできません(width と height は疑似要素のボックスの幅と高さを変更するだけです)。
svg 画像の幅と高さを変更するには、7行目の content の値の url() に指定した svg の width と height で調整する必要があります。
また、svg 画像の色は url() に指定した svg の fill 属性で設定することができます。
sample
<p class="icon-envelope1">sample</p>
.icon-envelope1::before{ position: relative; /* 位置 right を指定するために設定 */ right:10px; /* 位置(テキストとの距離)を調整(または left:-10px;) */ display: inline-block; /* 横並び(インライン) */ vertical-align: -3px; /* 垂直方向の調整 */ margin-left: 1rem; /* 左端の位置の調整 */ content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-envelope' viewBox='0 0 16 16'%3E%3Cpath d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z'/%3E%3C/svg%3E"); }
content の url() 関数に指定する値はダブルクォートで囲み、data:image/svg+xml,
の後に SVG のコードを URI エンコードした値を指定します。
値をダブルクォートで囲むため、 SVG のコードの属性の値はシングルクォートで囲みます。また、< は %3C、> は %3E、# は %23 に変換します(手動で変換するのが面倒な場合は、SVG エスケープツール をご利用ください)。
background-image に指定する例
以下は前述の封筒のアイコンを ::before を使って background-image に指定して表示する例です。
::before を使って background-image に svg を指定する場合、疑似要素の width と height で表示される画像の大きさを調整できます。
但し、svg のコードに width と height が指定してあると、追加で background-size: contain を指定するか、svg のコードの width と height を疑似要素の width と height に合わせる必要があります。
そのため、この例では以下のように svg 要素の width と height を削除したコード(以下)を URI エンコードして指定し、疑似要素の CSS で width と height で表示する幅と高さを指定しています。
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-envelope" viewBox="0 0 16 16"> <path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z"/> </svg>
sample
<p class="icon-envelope2">sample</p>
background-image に指定して svg を表示する場合、content を空にして、display: inline-block を指定し、width と height で指定したサイズの疑似要素の空のボックスを作成してそのボックスの背景画像として svg を表示します。
background-image の url() 関数に指定する値は、content に指定する場合と同様、ダブルクォートで囲み、data:image/svg+xml,
の後に SVG のコードを URI エンコードした値を指定します。
svg 画像の色は、content に指定する場合と同様、 url() に指定した svg の fill 属性で設定することができます。
.icon-envelope2::before{ content: ""; /* content を空に */ display: inline-block; /* 疑似要素の既定値の inline を変更 */ height: 32px; /* 疑似要素の高さ = 背景画像(svg)の高さ */ width: 32px; /* 疑似要素の幅 = 背景画像(svg)の幅 */ vertical-align:-10px; /* 垂直方向の位置の調整 */ margin-right: 8px; /* テキストとの距離 */ background-repeat: no-repeat; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='currentColor' class='bi bi-envelope' viewBox='0 0 16 16'%3E%3Cpath d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z'/%3E%3C/svg%3E"); }
svg 要素に width と height が指定されている場合は、CSS の background-size に contain を指定すると疑似要素の領域に画像全体が収まるよう拡大・縮小されます(この例の場合は cover でも同じ)。
または、svg 要素の width と height を疑似要素の width と height に合わせます。
.icon-envelope2::before{ content: ""; display: inline-block; height: 32px; width: 32px; vertical-align:-15px; margin-right: 8px; background-repeat: no-repeat; background-size: contain; /* 疑似要素の領域に画像全体が収まるよう拡大・縮小 */ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-envelope' viewBox='0 0 16 16'%3E%3Cpath d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z'/%3E%3C/svg%3E"); }
CSS アニメーション
以下は前述の ::before を使って background-image に指定して表示した封筒のアイコンに CSS アニメーションを適用する例です。
<p><span class="icon-envelope3"></span></p>
CSS では transition を追加して、ホバー時に rotate(360deg) でアイコンを回転させています。
:hover は疑似要素を挿入する要素に指定します。以下の場合は、icon-envelope3 クラスを指定した要素、つまり、.icon-envelope3:hover::before となります。
疑似要素は HTML として認識されないので、疑似要素に :hover を指定しても何も起きないので、.icon-envelope3::before:hover では動きません。
.icon-envelope3::before{ content: ""; display: inline-block; height: 32px; width: 32px; vertical-align:-10px; margin-right: 8px; background-repeat: no-repeat; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='currentColor' class='bi bi-envelope' viewBox='0 0 16 16'%3E%3Cpath d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z'/%3E%3C/svg%3E"); transition: 0.6s; /* transition を追加 */ } .icon-envelope3:hover::before { transform: rotate(360deg); }
以下は、ホバー時に scale(1.2) で拡大し、svg の fill 属性を gold に変更して色を変える例です。
.icon-envelope4:hover::before { transform: scale(1.2); /* fill を gold に */ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='gold' class='bi bi-envelope' viewBox='0 0 16 16'%3E%3Cpath d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z'/%3E%3C/svg%3E"); }
svg の要素が複数あれば、それぞれに異なる色を設定することも可能です。また、それぞれの要素に transform などを設定することもできますが、中心位置や viewBox の調整などが必要になります。
<p class="icon-box-arrow "><a href="#">Link</a></p>
.icon-box-arrow { font-size: 32px; } .icon-box-arrow a:hover { color: pink; } .icon-box-arrow::after { content: ""; display: inline-block; height: 32px; width: 32px; margin-left: 10px; background-repeat: no-repeat; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='currentColor' class='bi bi-box-arrow-up-right' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E"); transition: 0.6s; } /* 1つ目の path に fill='red' を、2つ目の path に fill='blue' を設定 */ .icon-box-arrow:hover::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='bi bi-box-arrow-up-right' viewBox='0 0 16 16'%3E%3Cpath fill='red' fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill='blue' fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E"); }
以下はアイコンの親要素にホバーすると疑似要素をアニメーションする例です。
sample
<p class="icon-animation"><span class="icon-envelope5"></span>sample</p>
.icon-envelope5::before{ content: ""; display: inline-block; height: 32px; width: 32px; vertical-align:-10px; margin-right: 8px; background-repeat: no-repeat; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='currentColor' class='bi bi-envelope' viewBox='0 0 16 16'%3E%3Cpath d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z'/%3E%3C/svg%3E"); transition: 0.6s; } /* 親要素の .icon-animation に :hover */ .icon-animation:hover .icon-envelope5::before { transform: scale(1.2); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='gold' class='bi bi-envelope' viewBox='0 0 16 16'%3E%3Cpath d='M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2zm13 2.383l-4.758 2.855L15 11.114v-5.73zm-.034 6.878L9.271 8.82 8 9.583 6.728 8.82l-5.694 3.44A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.739zM1 11.114l4.758-2.876L1 5.383v5.73z'/%3E%3C/svg%3E"); } .icon-animation{ transition: 1s; } .icon-animation:hover { color: green; }
アイコンの表示とアニメーションを分離
以下はアイコンの表示とアニメーションを別のクラスに分けて設定する例です。
この場合、icon-animation や icon-animation-rotateY を追加するとアニメーションが実行されます。色を変える必要がなければ汎用的なアニメーションのクラスを設定できます。
<ul> <li> <a href="#"> <i class="icon-facebook"></i> </a> </li> <li> <a href="#"> <i class="icon-facebook icon-animation"></i> </a> </li> <li> <a href="#"> <i class="icon-facebook icon-animation-rotateY"></i> </a> </li> </ul>
.icon-facebook::before{ content: ""; display: inline-block; height: 30px; width: 30px; background-repeat: no-repeat; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%233854EE' viewBox='0 0 16 16'%3E%3Cpath d='M16 8.049c0-4.446-3.582-8.05-8-8.05C3.58 0-.002 3.603-.002 8.05c0 4.017 2.926 7.347 6.75 7.951v-5.625h-2.03V8.05H6.75V6.275c0-2.017 1.195-3.131 3.022-3.131.876 0 1.791.157 1.791.157v1.98h-1.009c-.993 0-1.303.621-1.303 1.258v1.51h2.218l-.354 2.326H9.25V16c3.824-.604 6.75-3.934 6.75-7.951z'/%3E%3C/svg%3E"); } .icon-facebook.icon-animation::before { transition: 0.3s ease-in; } .icon-facebook.icon-animation:hover::before { transform: rotate(360deg) scale(1.2); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='pink' viewBox='0 0 16 16'%3E%3Cpath d='M16 8.049c0-4.446-3.582-8.05-8-8.05C3.58 0-.002 3.603-.002 8.05c0 4.017 2.926 7.347 6.75 7.951v-5.625h-2.03V8.05H6.75V6.275c0-2.017 1.195-3.131 3.022-3.131.876 0 1.791.157 1.791.157v1.98h-1.009c-.993 0-1.303.621-1.303 1.258v1.51h2.218l-.354 2.326H9.25V16c3.824-.604 6.75-3.934 6.75-7.951z'/%3E%3C/svg%3E"); } .icon-animation-rotateY::before { transition: 0.6s ease-in; } .icon-animation-rotateY:hover::before { transform: rotateY(720deg); }
Web Animation API でアニメーション
現時点では、CSS transition での疑似要素のアニメーションは Safari などでは期待通りに動作しません。
JavaScript の Web Animation API を利用して疑似要素をアニメーションすることができます。
<a href="#"> <i class="icon-facebook js-animation"></i></a>
疑似要素の CSS は前述の例と同じものです。但し、transition でアニメーションを実行する代わりに、Web Animation API を使って疑似要素をアニメーションします。
.icon-facebook::before{ content: ""; display: inline-block; height: 30px; width: 30px; background-repeat: no-repeat; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%233854EE' viewBox='0 0 16 16'%3E%3Cpath d='M16 8.049c0-4.446-3.582-8.05-8-8.05C3.58 0-.002 3.603-.002 8.05c0 4.017 2.926 7.347 6.75 7.951v-5.625h-2.03V8.05H6.75V6.275c0-2.017 1.195-3.131 3.022-3.131.876 0 1.791.157 1.791.157v1.98h-1.009c-.993 0-1.303.621-1.303 1.258v1.51h2.218l-.354 2.326H9.25V16c3.824-.604 6.75-3.934 6.75-7.951z'/%3E%3C/svg%3E"); }
mouseenter イベントと mouseleave イベントのリスナーを設定し、それぞれに別途 Web Animation API の animate() を使って定義した関数を呼び出しています。
//.icon-facebook.js-animation の要素をすべて取得 const iconFBJS = document.querySelectorAll('.icon-facebook.js-animation'); //取得したそれぞれの要素に iconFBJS.forEach((elem) => { //mouseenter イベントのリスナーを設定 elem.addEventListener('mouseenter', (e) => { //e.currentTarget はリスナーを登録した要素(iconFBJS) enterAnimation(e.currentTarget); }); //mouseleave イベントのリスナーを設定 elem.addEventListener('mouseleave', (e) => { leaveAnimation(e.currentTarget); }); }); // mouseenter で呼び出す関数 function enterAnimation(element) { const rotate = ["0deg", "360deg"] ; const options = { duration: 300, // pseudoElement プロパティに ::before を指定 pseudoElement: "::before", easing: 'ease-in', fill: "forwards" }; //引数に受け取った要素に animate() メソッドでアニメーションを設定 element.animate({ rotate }, options); }; // mouseleave で呼び出す関数 function leaveAnimation(element) { const rotate = ["360deg", "0deg"] ; const options = { duration: 300, // pseudoElement プロパティに ::before を指定 pseudoElement: "::before", easing: 'ease-in', fill: "forwards" }; element.animate({ rotate }, options); };
//取得したそれぞれの要素に iconFBJS.forEach((elem) => { //回転が適用されているか let isActive = false; //クリックイベントのリスナーを設定 elem.addEventListener("click", (e) => { if(!isActive) { //e.currentTarget は icon-arrow クラスを指定した要素 const rotateIcon = e.currentTarget.animate( { rotate: ["0deg", "360deg"] }, // options オブジェクト { duration: 300, // pseudoElement プロパティに ::before を指定 pseudoElement: "::before", easing: 'ease-in', fill: 'forwards', } ); isActive = true; }else{ const rotateIcon = e.currentTarget.animate( { rotate: ["360deg", "0deg"] }, // options オブジェクト { duration: 300, // pseudoElement プロパティに ::before を指定 pseudoElement: "::before", easing: 'ease-in', fill: 'forwards', } ); isActive = false; } }); });
SVG 背景パターン
SVG でパターンを作成して、CSS で svg 要素を背景画像に指定する例です。
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300" viewBox="0 0 300 300"> <circle cx="46" cy="56" r="17" fill="#f5ddf9"/> <path d="M90.5,118A31.5,31.5,0,1,1,59,149.5,31.5,31.5,0,0,1,90.5,118ZM197,61a19,19,0,1,1-19,19A19,19,0,0,1,197,61Zm40.5,93A30.5,30.5,0,1,1,207,184.5,30.5,30.5,0,0,1,237.5,154Zm-127,69A10.5,10.5,0,1,1,100,233.5,10.5,10.5,0,0,1,110.5,223Z" fill="#f5ddf9"/> </svg>
以下は上記 SVG をインラインで表示したものです(実際より小さく表示しています)。
上記 SVG を background-image に指定して背景パターンにします。
background-image に url() で指定する際は、data:image/svg+xml に続けて URI エンコードした SVG コードを指定し、値全体をダブルクオートで囲みます。
background-repeat のデフォルトは repeat なのでこの場合、繰り返し表示されます。また、以下の例では linear-gradient でグラデーションも同時に指定しています。
.sample_bg { background-image: linear-gradient(120deg, rgba(3,131,169,.01), rgba(3,131,169,0.3)), url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300' viewBox='0 0 300 300'%3E%3Ccircle cx='46' cy='56' r='17' fill='%23f5ddf9'/%3E%3Cpath d='M90.5,118A31.5,31.5,0,1,1,59,149.5,31.5,31.5,0,0,1,90.5,118ZM197,61a19,19,0,1,1-19,19A19,19,0,0,1,197,61Zm40.5,93A30.5,30.5,0,1,1,207,184.5,30.5,30.5,0,0,1,237.5,154Zm-127,69A10.5,10.5,0,1,1,100,233.5,10.5,10.5,0,0,1,110.5,223Z' fill='%23f5ddf9'/%3E%3C/svg%3E"); min-height: 400px; max-width: 700px; width: 100%; } .sample_bg p { text-align: center; color: #fff; line-height: 400px; text-shadow: 1px 1px rgba(0,0,0,.4); font-size: 20px; }
<div class="sample_bg"> <p>Sample Background</p> </div>
Sample Background
background-size
以下は background-size を指定してパターンの大きさを調整する例です。
.sample_bg2 { background-image: linear-gradient(120deg, rgba(3,131,169,.01), rgba(3,131,169,0.3)), url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300' viewBox='0 0 300 300'%3E%3Ccircle cx='46' cy='56' r='17' fill='%23f5ddf9'/%3E%3Cpath d='M90.5,118A31.5,31.5,0,1,1,59,149.5,31.5,31.5,0,0,1,90.5,118ZM197,61a19,19,0,1,1-19,19A19,19,0,0,1,197,61Zm40.5,93A30.5,30.5,0,1,1,207,184.5,30.5,30.5,0,0,1,237.5,154Zm-127,69A10.5,10.5,0,1,1,100,233.5,10.5,10.5,0,0,1,110.5,223Z' fill='%23f5ddf9'/%3E%3C/svg%3E"); background-size: 100px 100px; min-height: 400px; max-width: 700px; width: 100%; }
Sample Background
以下はグラデーションには background-size で cover を、background-repeat で no-repeat を指定する例です。
.sample_bg3 { background-image: linear-gradient(120deg, rgba(3,131,169,.01), rgba(3,131,169,0.3)), url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300' viewBox='0 0 300 300'%3E%3Ccircle cx='46' cy='56' r='17' fill='%23f5ddf9'/%3E%3Cpath d='M90.5,118A31.5,31.5,0,1,1,59,149.5,31.5,31.5,0,0,1,90.5,118ZM197,61a19,19,0,1,1-19,19A19,19,0,0,1,197,61Zm40.5,93A30.5,30.5,0,1,1,207,184.5,30.5,30.5,0,0,1,237.5,154Zm-127,69A10.5,10.5,0,1,1,100,233.5,10.5,10.5,0,0,1,110.5,223Z' fill='%23f5ddf9'/%3E%3C/svg%3E"); background-size: cover, 200px 200px; background-repeat: no-repeat, repeat; min-height: 400px; max-width: 700px; width: 100%; }
Sample Background
SVG 背景パターン関連のサイト(SVG Pattern Generators などで検索すると色々と出てきます)
- SVG Backgrounds(無料で使う場合はクレジットの記載が必要)
- Hero Patterns
- SVG STRIPE GENERATOR
- SVGeez
- PATTERN MONSTER
- PatternPad
path 要素の CSS アニメーション
Chrome や Firefox などの CSS の d プロパティをサポートしているブラウザでは、path 要素の d 属性の値を使ってアニメーションが可能です。
以下はホバー時に path 要素の d 属性の値を変更してトランジションアニメーションを設定した例です。Chrome または Firefox で確認してください(Safari ではアニメーションされません)。
また、最後の A コマンドを使った半円は少し変わった動きになります。
<svg viewBox="0 0 100 100" class="svg-01"> <path d="M 10 50 Q 50 0 90 50"/> </svg> <svg viewBox="0 0 100 100" class="svg-02"> <path d="M 10 50 C 20 10 40 10 50 50 S 70 80 90 50"/> </svg> <svg viewBox="0 0 100 100" class="svg-03"> <path d="M 10 50 L 50 10 L 90 50"/> </svg> <svg viewBox="0 0 100 100" class="svg-04"> <path d="M 10 10 L 90 10 L 50 90 L 10 10"/> </svg> <svg viewBox="0 0 100 100" class="svg-05"> <path d="M 10 10 L 90 90 L 10 90 L 90 10 L 10 10"/> </svg> <svg viewBox="0 0 100 100" class="svg-06"> <path d="M 10 50 A 40 40 0 1 1 90 50"/> </svg>
path 要素のアニメーションの場合、d 要素の値が正確に同じ数の頂点を持ち、同じコマンド及び順序で記述される必要があります。
svg { width: 100px; height: 100px; } svg path { fill: transparent; stroke: #000; stroke-width: 3px; stroke-linecap: round; stroke-linejoin: round; transition: 0.4s; /*トランジションを設定*/ } .svg-01:hover path { d: path("M 10 50 Q 50 90 90 50"); } .svg-02:hover path { d: path("M 10 50 C 20 90 40 90 50 50 S 70 20 90 50"); } .svg-03:hover path { d: path("M 10 50 L 50 90 L 90 50"); } .svg-04:hover path { d: path("M 10 90 L 90 90 L 50 10 L 10 90"); } .svg-05:hover path { d: path("M 10 10 L 90 10 L 90 90 L 10 90 L 10 10"); } .svg-06:hover path { d: path("M 90 50 A 40 40 0 1 1 10 50"); }
以下はいずれも d 属性の値を折れ線から直線へ変更する例ですが、2つ目の場合、 d 属性の頂点(データポイント)の数が異なるのでスムーズなアニメーションにはなりません。
<svg viewBox="0 0 100 100" class="svg-07"> <path d="M 10 50 L 50 10 L 90 50"/> </svg> <svg viewBox="0 0 100 100" class="svg-08"> <path d="M 10 50 L 50 10 L 90 50"/> </svg>
svg path { fill: transparent; stroke: #000; stroke-width: 3px; stroke-linecap: round; stroke-linejoin: round; transition: 0.4s; /*トランジションを設定*/ } .svg-07:hover path { d: path("M 10 50 L 50 50 L 90 50"); } .svg-08:hover path { d: path("M 10 50 L 90 50"); /*頂点の数が異なる*/ }
以下はキーフレームを使ったアニメーションの例です。
<svg width="300px" height="180px" viewBox="0 0 300 180" > <path id="css_path_animation" d="M10 10 C50 100,90 140,150 60 S230 0,280 6" stroke="blue" stroke-width="3" fill="transparent"/> </svg>
#css_path_animation { animation: change-d 4s ease-in-out infinite alternate both; } @keyframes change-d { 0% { d: path("M10 10 C50 100,90 140,150 60 S230 0,280 60"); stroke: cornflowerblue } 100% { d: path("M 10 100 C 90 -100, 120 80, 160 60 S 240 160, 280 60"); stroke: forestgreen } }
基本図形要素(ellipse)の CSS アニメーション
以下は ellipse 要素の ry 属性を使ったホバー時のアニメーションの例です。
※ Chrome のみで機能します(それ以外のブラウザではアニメーションしません)。
<svg viewBox="0 0 100 100" class="svg-e01"> <ellipse cx="50" cy="50" rx="47" ry="22"/> </svg>
svg ellipse { fill: transparent; stroke: #000; stroke-width: 3px; transition: 0.4s; /*トランジションを設定*/ } .svg-e01:hover ellipse { ry: 47; }
requestAnimationFrame() を使えば Chrome 以外のブラウザでも同様のアニメーションを実装できます。
関連ページ:requestAnimationFrame の使い方
また、CSS の clip-path アニメーションを使う方法もあるかと思います。
関連ページ:CSS clip-path の使い方