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

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

13.連携・拡張

本項ではsvgにおける「連携」機能に焦点を当てる.これらの機能はsvgがxmlをベースとした言語であることに由来し,他のベクタ画像形式と一線を画すものとなっている.応用次第では非常に強力な機能となる.

a:外部文書へのリンク

a要素を用いるとsvg内部から(html等の)外部文書へのリンクを張ることが出来る.このa要素はhtmlのものとは異なるため,リンク先の指定にはxlink:href属性を用いる.なおこのhref属性はxlinkで定義されているものである.svgをhtmlと同様に扱うことも可能なことから,単純な機能ながらsvgを他の画像形式と一線を画す重要な機能と言える.例えば,組織図をsvgで記述し,部門毎のrect要素に各部門のフロントページへのリンクを張ると言った用途に使える.

埋め込みsvg要素においては通常htmlのa要素でsvg要素を囲んでもリンクが有効とならないが,この代替として利用することができる.なお,svgが画像として利用されている場合(img要素から参照しているケース)においては無効となる.

xlink:href
リンク先の指定
target
リンクを開く先の指定(htmlと同様)
_replace
svgのリンク領域がリンク先のsvg画像に置き換わる.なお,対応しているブラウザは不明.
_self
自分自身を入れ替える.(規定値)
_parent
親フレームに表示.
_top
自身が表示されているタブ・ウインドウに表示.
_blank
新たなタブ・ウインドウに表示.
[name]
指定した名称のフレーム・ウインドウに表示

リンクの範囲

svgにおいてはa要素で囲んだ図形要素・テキスト要素の描画領域がクリッカブルに設定される.従ってcircle要素をa要素に挿入した場合は円形のクリッカブル領域となる.なおクリック有無の判定にはpointer-events属性によるのイベント発生設定が関わっている.

下のcircleはクリックできます. _replace _self _parent _top _blank

svg文書をobject要素,embed要素で表示している場合は,概ねiframeで表示するケースと同じ動作をとる.下に例を示したので,実際に試してみると良いだろう.

iframeobjectembed

文字列の一部にリンクを設定する

text要素をa要素で囲む他にa要素をtext要素に含めることで文字列の一部にリンクを設定することが出来る.この時のa要素はtspan要素の代替として存在しているわけではないため,x属性やy属性を設定することは出来ないがプレゼンテーション属性による見た目の装飾は可能である.

文字列の一部にリンクを挿入

リンク先が特定のsvg要素であった場合,特有な動作を摂る場合がある.

animate要素

リンク先のanimate要素のbegin属性に「indefinite」を設定しておき,リンクをクリックすることでアニメーションが開始されるようになる.

click me!

view要素

リンク先がview要素だった場合,svg要素の持つviewBoxがview要素の持つものに設定される.なお,インラインsvgでは動作しない.

click me! click me!

この動作はiframe/object要素でsvgを参照している場合に確認できる.実際に下の例をクリックしてみて欲しい.

<?xml version="1.0" standalone="no"?>
<svg width="200px" height="200px" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
    <view id="view1" viewBox="0 0 100 100" />
    <view id="view2" viewBox="100 100 100 100" />
    <a xlink:href="#view2">
        <circle cx="60" cy="60" r="50" fill="red"/>
        <polygon points="100,50 50,140 150,140" fill="yellow"/>
    </a>
    <a xlink:href="#view1">
        <rect x="80" y="120" width="100" height="60" fill="blue"/>
    </a>
</svg>

use要素との連携によるハイパーリンクのモジュール化

a要素によるリンク設定はuse要素によってコピーすることが可能だ.

  1. リンクを定義したい図形をa要素で囲む.
  2. これを更にg要素で囲む.
  3. このg要素にidを振り,use要素から参照する.

例を示す.

ここではインラインsvgでリンクを定義しているが,これを外部svgファイルに設定しても同様の結果となる.このようにsvgを用いるとハイパーリンク情報を外部svgファイルにまとめることができる.つまりhtml単体では難しかった複数ページにまたがるリンク情報の一元管理が可能となるのだ.

但しこのテクニックは,use要素が外部ファイルを参照する場合に問題を引き起こす.リンク先の内容が「相対位置指定」及び「ハッシュ(#[id])指定」の場合にブラウザ毎に動作が異なるためだ.firefoxにおいてはコピーしたリンクが元となるsvg要素のパスを基準に解釈され,chrome/operaではコピーした文書側を基準に解釈されるのだ.例を挙げよう.a.htmがa.svgを使ってリンク情報「#a」をコピーしたとしよう.firefoxでは「a.svg#a」として,chrome/operaでは「a.htm#a」として解釈される.よって,環境によってリンク先が変化する結果となる.

foreignObject:外部型オブジェクトの埋込み

※このセクションのサンプル実行例には動作が不安定なものが含まれています.これはスクリプトを介してdomを書き換えることで発生しているようなので,正しい動作は[編集]ボタンをクリックして確認してください.(結構動作しています)

foreignObject要素はグラフィックの描画にsvg以外の要素を用いることを表す.例えばこの要素の配下にhtmlを記述することで,グラフィックの一部がhtmlで描画されるようになる.その他にも独自の要素を定義して挿入することができるが,グラフィックを正しく表示するには,svgを表示する側でその機能をサポートしていなければならない

その為foreignObject要素は本来単体で利用されることは無く,switch要素と組み合わせて用いられる.switch要素はsvgビューアがサポートする機能により描画する内容を切り替えるためのもので,例えばドローイングツールが独自機能を用いて作成したsvgファイルを環境によって代替画像に切り替えると言った事が可能となる.同様にsvgにhtml要素を挿入した場合は,htmlを解釈できないアプリケーションの為に,switch要素を用いて適切な代替画像を表示できるようにしておくことが望ましい.

なおインラインsvg要素の場合は,ユーザーエージェント(ここではwebブラウザ)がhtmlを解釈出来るはずなのでそれほど問題はない.

foreignObject要素で描かれた(html文書等の)画像はsvgから見た場合図形として扱われる.その為,filter等の効果を付けることが出来るはずなのだが,ブラウザ間における動作の差異が非常に大きく,実際に使い物になるかどうかについては精密に動作検証を行う必要がある.というのも,foreignObject要素の役割上,どのような動作が望ましいかについては含まれている内容によって異なるため,深くは言及されていないのだ.従ってsvgに簡単なhtmlを挿入すると言ったケースにおいても,ブラウザ毎に大きく動作が異なるケースがある.例えばhtmlのスクロールバーの機能をsvgに導入したい場合,svg-html-svgと言ったような階層構造を考えることができるが,実際に試してみると動作しない場合が多い.

ここでは例としてhtml-svg-htmlといった入れ子の例を示す.form要素をsvg要素の外側で定め,form部品をforeignObject要素の内側に定義した.

何れにせよ,foreignObject要素を積極的に利用するには余りに不確定要素が多いため,出来る事なら使わずに済ませたいところである.

xmlns
foreignObject要素配下の要素が属す名前空間.html埋め込みsvgの場合は記述を省くことで自動的にhtml要素として解釈される.(svg単体やxhtml埋め込みの場合はこの限りではない)
svgのフィルターが掛かっているので,このinput要素にはぼかしがかかっています.

内部のコンテンツが参照する座標系

foreignObject内部のコンテンツは,foreignObject要素が参照している座標系を元に描画される.その為,内部のhtmlの要素が単位pxを参照していたとしても実際の大きさはsvgの設定に左右される.

100px×100px

htmlのコンテンツモデルを利用する

唯一利用価値が有りそうなものが次の文字列の折り返しである.htmlのdiv要素を導入することでsvg単体では難しかったテキストの折り返しを実現することが出来る(将来的にはsvg単体で実現出来るようになるようだ).しかしこの用途においてすら,cssの指定方法によってはブラウザ毎に動作が変化する.よってどうしてもforeignObject要素を使う必要がある場合も,出来うる限りシンプルな構造に留めておくのが上手く付き合うコツであろう.なお,スタンドアロンのsvgにhtmlを埋め込む場合は別途body要素を用意する必要があるかも知れない.特に問題はない.

svg単体では実現不可能であっても,(x)htmlの要素を利用することで,例えばこのようなテキストの折り返しを実現することもできる.よってsvgの仕様はグラフィックの描画に特化したものとなっているのだ.

埋め込みsvgのフォールバックコンテンツとしての利用

埋め込みsvgを用いた場合は,foreignObject要素を用いてフォールバックコンテンツを定義することができる.foreignObject要素の配下にimg要素を記述すると,svgを解釈出来ないブラウザではimg要素がsvg要素の外に有るものとして描画される.逆にsvgに対応した環境ではこのimg要素が表示されないようにforeignObject要素にはdisplay="none"を施しておく.実際にie8とandroid2にて動作を確認した.

<!DOCTYPE html>
<html>
    <body>
        <svg>
            <foreignObject display="none">
                <img src="img.png"/>
            </foreignObject>
        </svg>
    </body>
</html>

スタンドアロンのsvgにファビコンを追加する

webブラウザにおけるファビコンの表示機能は元来html向けであるが,スタンドアロンのsvgにおいてもhtmlのlink要素の機能を借りることでファビコン設定を行うことが出来る(chromeを除く).例を示す.画像をクリックすると別ウィンドウで表示します.

<?xml version="1.0" standalone="no"?>
<svg width="200px" height="200px" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
    <foreignObject>
        <link xmlns="http://www.w3.org/1999/xhtml" rel="shortcut icon" href="favicon.png"/>
    </foreignObject>
    <text y="20">ファビコン画像設定済</text>
    <image xlink:href="favicon.png" x="50" y="50" width="100" height="100" image-rendering="optimizeSpeed"/>
</svg>

metadata:相互運用のための要素

svgはxmlで定義されているため,一般のxmlを処理可能なシステムで取り扱うことができる.独自データ(要素)をsvgファイルに挿入する場合,その挿入位置に技術的な制限はないが,全体での統一を図るために,このmetadata要素の子として記述することが推奨されている.よって,svgでグラフィックを描く場合はそれほど意識せずとも良い.

metadata要素を使った背景画像のフォールバック

インラインsvgでmetadata要素を扱う上で,唯一利用価値のある応用として背景画像のフォールバックが挙げられる.svgをサポートしないwebブラウザにおいて背景画像にsvg画像を指定した場合,何も表示されない.従ってsvgをサポートしない環境でのみ効力を発揮するスタイルシートを定め,その中でフォールバック画像への振替を行う必要がある.

その際,予めインラインsvg要素を定義しておき,その中にmetadata要素,及び(htmlの)link要素を配置することでこの動作を実現することができる.例を示す.

<!DOCTYPE html>
<html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <style>
        div{
            height:100px;
            background-image:url("sample.svg");
        }
    </style>
    </head>
    <body>
        <svg display="none">
            <metadata>
                <link rel="stylesheet" href="fallback.css" type="text/css"/>
            </metadata>
        </svg>
        <div>
            この部分の背景はsvgのサポート状況により切り替わります.
        </div>
    </body>
</html>
link要素の参照先
div{
    background-image:url("fallback.png");
}

動作原理は次のとおりである.

  1. svgをサポートする環境の場合
    • svg要素の内部はhtmlとは異なるコンテキストの領域として扱われる.
    • その内部に含まれたlink要素はhtmlにおけるlink要素とは解釈されず,レンダリング処理上無視される.
  2. svgをサポートしない環境の場合
    • svgに関わる要素を正しく解釈することが出来ないため,svg要素はレンダリング上無視される.
    • 内部にあるlink要素はhtmlで定義された要素としてsvg要素の直後に存在するものとして解釈される.
    • body要素内部に発見されたlink要素はhead要素で宣言されたものとして扱われる.

この動作はwebブラウザの標準動作として定められているため,レガシーie及びsvgをサポートしないandroid os標準webブラウザでも正しく動く.

※なおmetadata要素を用いずともsvg要素の直下にlink要素を配置しても動作するが,svgの意味上不正な構成となってしまう点に注意しよう.

metadata要素の動作はhtmlのインラインsvgとスタンドアロンsvgとで異なる.htmlのインラインsvgの場合は,htmlのパージングの段階で要素名を元に自動的に所属する名前空間が定まる.その際,metadata要素内部の(div等の)一部のhtml要素は,記述ミスとして扱われsvg画像の範囲外に再配置される.その結果,metadata要素内部に挿入した内容がスクリーンに表示されるケースが発生する.先ほどの例においては,link要素はたまたまこの対象から外れていたためにレンダリング処理において無視される結果となった.