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

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

1.svgの基礎知識

本項ではsvgを取り巻く背景や,その特徴・役割について解説する.グラフィックを描きたいだけなら読み飛ばしても差し支えないが,なぜ今更svgなのか,svgが存在する意義を知っておくことで,適切な技術の選択が出来るようになるはずだ.

svgとは

svg(Scalable Vector Graphics)とはxml(eXtensible Markup Language)を基盤とした2次元画像記述言語である.w3cにより標準化された.svgで記述されたsvgファイル(拡張子.svg)はjpgやpng等の画像ファイルと同様にグラフィックビューアやブラウザ等での表示が可能である.

このsvg形式の画像の特徴としては次のようなものが挙げられる.

1・ベクタ形式のグラフィックを表現する

2・高度なユーザーエクスペリエンスを演出する

3・xmlベースのグラフィカルな文書形式である

4・柔軟なグラフィックのモジュール化機構

ちなみに規格そのものは2001年当時から存在していたが,本格的に利用されるようになってきたのはごく最近のことである.当初様々なアプリケーションにおいて単なる画像出力形式としてsvgをサポートしたため,多くの人々からはあまたあるベクタ画像形式の中の一つと見なされていた.そのため,webブラウザの分野では似たような技術(css2・3やcanvas要素)が注目を集める中で今ひとつ盛り上がりに欠けたままであった.が,近年のwebブラウザがリッチクライアント化する流れの中で,少しづつsvgの持つ可能性(アニメーションやxmlベースであることのメリット)が再評価され,html5においては埋め込みsvg要素として採用されるに至る.このことでようやく各種webブラウザでのsvgネイティブ対応が進み,将来における利用拡大が見込まれることとなったのだ.またInternet Explorer9がsvgをサポートすることを表明したことも,再びsvgが注目を集める大きなきっかけとなった.

と言ったことからこの先重要な役割を果たすと思われるsvg技術ではあるが,まだテクニック・パフォーマンスと言った実装・利用に関わる部分のナレッジの蓄積に乏しい.svgの持つ広大な仕様をフルに活用しようとする場合,どこにウィークポイントが存在するのか全くの未知数である.現状でも凝ったことをした際に,強烈なパフォーマンスの低下を引き起こすケースがある.また,広範な環境で動作するとはいいつつも,実際に試してみると環境によって細かい部分の動作に違いが見られ,思い通りの結果が得られないこともしばしばである.将来的に改善されることを期待しつつも,今をどう乗り切るかと言った点でリスクが存在する.

※イメージしにくい場合,「svgはグラフィックを描くプログラム(スクリプト)言語」であることを意識してください.文法を一から定義するのが面倒だったため,htmlとの親和性の高いxmlを流用しているわけです.したがってsvg画像は元を正せば「プログラムコード」であり,ラスタ画像の「データ形式」とは根本的に仕組みが異なっています.またxmlを利用することで副次的にコードの再利用性や編集性が高められている点に注意しましょう.これらのメリットは実際にsvgを利用してくうちに自ずと理解できていく筈です.

svgの規格

svgの仕様は多岐に渡るため,用途に応じてそのサブセットが規格として策定されている.

よってsvg basic,svg tinyにおいては使用可能な要素・属性・設定値・単位に制限があり,より軽快に動作するように設計されている.とは言え,最近では携帯機ですらフルスペックのwebブラウザを動作させ得るくらいに機能が向上してきたため,規格の選定自体にはそれほど意味が無くなりつつある.詳しくはこちらを参照のこと.

svgのバージョン

svgはバージョンが上がる毎に機能を充実してきたが,その遍歴を少したどってみよう.

この内よく用いられるものはsvg1.1second editionであり,現在svgといえばこのバージョンを指すものとして考えて良い.

svg1.2について

svg full 1.2は当初svg tiny 1.2の勧告の後,その機能をベースとして編纂される予定であった.実際w3cでは先行して検討されていたsvg print等の資料が未だに公開されている.が,いざ蓋を開けてみると土台となるべきsvg tiny 1.2の内容が世間のニーズとかけ離れてしまっていたため1.2の勧告化は中止となってしまった.そのため,サブセットの方がバージョンが高いという奇妙な状況が続いている.このような経緯は開発者側にも少なからず混乱をきたしたために,svg tiny 1.2をサポートする環境が少ないにもかかわらず,ツールによっては規格として存在しないsvg1.2による出力を試みるものがあったりと利用者側から見て非常に困った状況にある.

そのためsvgを取り扱うアプリケーションによっては,このバージョンの微妙な差異により描画結果が変化するケースがある.特にsvg tiny 1.2では文字列の描画処理が拡張されており,この機能を用いたsvg文書をsvg1.1にしか対応していない環境で開こうとした場合,文字列が描画されない結果をもたらす.このような不具合に遭遇した場合はバージョンの差異を疑いたい.Microsoftが当初svgのサポートに慎重だったのもこのような背景があったからかも知れない.

†svg単体でuiを構成するアイディアは当初魅力的であったが,仕様が確定した頃にはモバイル機器の機能向上に伴い事実上意味のないものとなってしまった.

svg2について

元々htmlとsvgとは親和性の高い技術だったが,html5にsvg仕様を統合するにあたり,基本となったsvg1.1では機能的な重複や論理的な不整合が発生してしまった.またsvg1.1仕様は既に古い規格であったため,現状のweb技術と比較し見劣りする部分も出ていた.そこでsvg2では一旦svgとhtmlの(cssに関わる)仕様を整理・統合し,全体として大きなweb仕様として再編されることとなった.従ってこれまでの汎用性を重視していたのとは対照的に,svg2ではより具体的なweb用途に特化したものとなる.但しその代償として「svg2」としての明確な仕様の境界が存在しなくなる点に注意しよう.つまりsvg仕様は複数のモジュールに分割され,今後それらの総称としての「svg」と言った意味合いを持ちつつある.

※そのため,今後svg1.1とsvg2の使い分けが必要となってくるかも知れない.

※なおsvg2はsvg1.1seの後継であり,svg1.2においては機能の一部が引き継がれるに留まる.よってsvgにおいては(かつてhtmlがそうであったように)バージョンごとの互換性に注意を要する.

svgの動作環境

2014年現在,モダンブラウザのほとんどでsvg(1.1 full)を利用することが可能である.が,ブラウザ毎に少しずつ対応状況が異なる.svgの全ての機能をサポートしたブラウザは存在せず,製品ごとに得意とする分野が存在する点を考慮すること.詳しくはWhen can I use...で調べることができる.なお,svgの動作傾向はブラウザが利用しているレンダリングエンジンの種類によって大体分類可能である.

ここで現存するシステムを鑑みた際に問題となりそうなものは,8以前の古いバージョンのinternet explorerとバージョン2以前のandroid osである.この2系統は他の環境と異なり容易にバージョンを変更することができないため,何らかの対策を施す必要がある.またie9,safari,chromeはsvg機能に難があるため,クロスブラウザを目指すのであれば,これらのブラウザを基準に考える必要がある.

レガシーieへの対策

大きなシェアを誇っていたwindows xpのサポート期間が終了するにあたり,レガシーie(つまり8以前のie)のうち考慮すべきものはwindows7環境のie8のみとなった.また,ie12では一度無効化されていたレガシーie互換モードが再度有効となる.以上のことから今後ようやくシステム上の制約からレガシーieを使い続ける必要はなくなった.

従って,下記の対策はwindows xp環境でかつて行われていたものとして憶えておけば良い.

android osへの対応

バージョン3に充たないandroid osでは上でのレガシーieと似た状況がある.汎用パーソナルコンピュータと比較し,携帯機器のosを変更することは非常に面倒な場合が多く,そもそもバージョンアップが出来ないと言ったこともざらである.そうは言っても現状大勢を占めるバージョン2系の環境を無視することは現実的では無いため,svgを導入する上で甚だ厳しいといった状況ではあるが,android osブラウザには辛うじてcanvas要素が存在するため,下記に示すjavascriptライブラリを用いることで擬似的にsvgを出力することが可能である.

携帯電話などのデバイスは比較的世代の交代が早いため,安心してsvgが利用可能となるためにも,なるべく早い内のシェアの縮小を願うばかりである.

svgの編集環境

本文書においてはテキストエディタによるsvgグラフィックの記述をメインに置いているが,一般には専用のアプリケーションを用いることが多い.市販のベクタ形式のドローイングツール(Adobe illastrator等)であるなら,svg形式での画像のエクスポートが可能のはず.その他,Microsoft Visio,花子を代表とする図面を引くツール等,意外なアプリケーションがsvgでの出力に対応していたりするので,手持ちの環境を調べてみるのも面白い.但し,svgが持たないアプリケーション独自の機能は削除されてしまう点には注意が必要である.また,出力したsvgファイルをブラウザが正しく表示できるかについても確認しておこう.

その他,無償で利用可能なツールも色々存在する.

これ以外にも様々なものがあると思うが,それぞれ得意とする分野があるため適宜選択すると良い.

但し,テキストエディタで作ったsvgファイルを他のツールで編集・保存した場合,そのツールが対応していない要素(例えばanimate要素)の情報が消えてしまうケースがある.作業の都合上,様々な環境でsvgを編集する必要がある場合は,事故を未然に防ぐため,svgの機能を複数のファイルに分けておこう.その方法についてはuse要素の部分で示す.

svgの応用

svgの利用サンプルが広まるにつれ,次第にsvgの向き不向きが明確になってきた.汎用的に設計されたsvgではあるが,以下ユースケース毎にその注意点について検討してみよう.

svgを手書きする理由

本文書ではsvgをテキストエディタで構築する為のサンプルを紹介するものだが,svgをこのように手で編集するメリットとは何だろうか?

  1. 幾何的な図案を描く場合は,絶対座標位置を直接指定できる手入力編集のほうが有利である.
    視覚的なツールではこの微妙な座標合わせが非常に面倒である.スクリプトを使って描画処理を自動化しても良い.
  2. 図形の構造化を行うことで,svgファイルサイズが最適化される.
    図形パターンの利用,図形のコピー,図形のグループ化,スタイルシートの適用等を駆使することで冗長なコードを排除することができる.また,各種ツールの埋め込みデータが存在しない分コード量が少なくて済む.
  3. なにより,後で変更するのが簡単.
    構造化されたsvgファイルであれば,図案を後から修正する際もテキストエディタでプロパティの編集を行うだけで済む.
  4. ドローツールが必要ないため,環境を選ばず編集することが可能.
    テキストエディタで編集し,ブラウザで動作を確認すれば,いちいち動作の重いドローツールを使って編集を行う必要が無くなる.
  5. アニメーションやフィルター等ツールが対応していないsvgの機能を利用することができる.
    これらの機能はまだツールでの実装支援機能の対応が遅れているため,直接入力による設計・実装が有効である.

要するに,svgを画像形式と捉えるのではなく,画像を生成するスクリプト言語として捉えると納得しやすいかと思う.実際,アニメーションやフィルターを定義する作業は処理順序を考慮したり,イベントの制御を行ったりとプログラミング感が高く,手作業でないと上手く扱えない印象がある.図形の描画はツールで行い,その仕上げを手で行うといったところか.

canvas要素との違い

svgと同様にhtml5ではグラフィックを描く要素としてcanvas要素が導入された.似たような役割を持つ要素は一つに集約すべきであるところ,わざわざ仕様に取り込まれたからには何らかの意味があるはずだ.ではsvgとcanvasとでは何が異なるのだろうか?

svgによる描画 canvasによる描画

基本的な比較

canvas要素ではブラウザ内部にcanvas要素のサイズ(縦×横×4(rgba)バイト)の描画メモリ領域が確保される.canvas要素のもつapiをjavascriptから操作し,この(グラフィック)メモリ領域にアクセスすることで画像を構成していく.一度描画された画像はhtmlページが破棄されるまでcanvas要素内に保持される.メモリに色情報を逐次上書きしていく為,その操作は不可逆的であり,アニメーションを行う場合などは1コマづつ再描画するロジックが必要となる.作成された画像は他のimg要素で読み込まれた画像と同等に取り扱われるため,要は動的にラスタ形式の画像を生成しているだけと考えれば良い.カンバスサイズが小さいうちはそれほど感じないが,大きくなるにつれて処理が重くなったり,描画完了後は軽快に動作するのはこのためである.また,非常に低レベルな(描画メモリに直接アクセスできる)apiが提供されていることにより,汎用的なグラフィック生成ロジックの移植についても比較的容易である.

一方svgによる描画はその手続きが要素として記述されており,全てをjavascriptで記述する必要のあるcanvasと比較して見通しが良い.またsvgの要素はdomツリーとしてブラウザ内部に保持され,javascriptを経由して設定値を書き換えることができる.domが変更されるとブラウザが自動的にグラフィックを書き換えてくれるため,canvasで必要だった再描画の処理を考慮する必要がなく,スクリプトの内容が短くなると言ったメリットがある.つまり,svgは2次元画像描画フレームワークと言える.従ってsvgでの描画はその設計思想に則った記述をする必要があり,canvas要素ほどの自由度はない.予めsvgで定義されている要素の範囲内で処理を行うこととなる.とは言え,svgの仕様は広範に渡るため,一般的な利用にあたってはそれほど問題が出るケースは考えにくい.また,複雑な画像となるとhtmlと比べ物にならないほどにdomに展開される要素の数が増加するため,パフォーマンスの低下が予想される.

このように2つの間には動作上に明快な違いがある.従ってcanvas要素はhtmlとしての可能性を広げる目的(要するにマルチメディアに関わる機能の強化.audio要素,video要素とセット.)で導入され,svg要素はhtmlの利便性を高める目的で導入されたことが想像できる.目的が異なるので2系統の要素が存在しているのだ.

なお,canvas要素がベクタ画像を描画するためのapiを提供すると説明されることがあるが,これはあながち間違いではない.カンバスサイズと内部の座標系とを適切に変換することにより,同一のスクリプトで解像度に応じた画像を描画することができるからだ.またsvgも最終的にはラスタ画像に変換(ラスタライズ)された上でディスプレイに描画される点に注意しよう.つまり,結果として得られる画像についてはsvg要素を用いようがcanvas要素を用いようがそれほど変わらないのだ.

svgとcanvasの実際

先ほどの記述は原則論であり,実際に技術の選定を行う場合はそれ以外に考慮すべき点が多い.その最たるものとしてcanvasは比較的ブラウザ間の動作の差異が少ない点が挙げられる.

これは元々のcanvasが提供するapiが控えめで,グラフィック描画処理における低レベルな機能を明快に定義しているため,ブラウザの開発者側でもそれほど迷うこと無く実装できているということである.svgはグラフィック描画を高度に抽象化しており,様々なユースケースを想定している内に仕様が非常に判りにくくなってしまった.そのためブラウザ開発者の解釈の相違を招き,ブラウザ間の動作の差異として現れてしまっており,一部機能においてはクロスブラウザ要件を満たすには程遠いと言った現状がある.一方svgを使う側においても高度な知識と熟練が要求されるため,javascriptさえ知っていれば絵を描けるcanvasにどうしてもシェアを奪われがちである.

その上,本来svgの持つベクタ画像としての優位性も単にブラウザで表示させる用途ではいささかオーバースペックであり,最低限スクリーンの解像度でグラフィックを描ければ良いと言った要件ではcanvas要素で十分目的を達成可能なため,積極的にsvgを推す根拠とはならない.今後canvas要素の機能向上により高解像度スクリーンに対応するapiが実装されるとますますsvgの影が薄くなる可能性すらある.

ではどのように選択するのが良いのか?svgはやはりマークアップでグラフィックを描けるというメリットを最大限に活かすのが良い.簡単なアニメーションであればわざわざscriptを用いずともsvgの機能を用いれば簡単に実現できる.構造が肝となるuiの設計であればdomとして要素が展開されるsvgの方が扱いやすいし,この程度の使い方であればブラウザ間の動作の差異に頭を悩ますことも無い.一方大量のスクリプトを駆使し複雑な動作を行うグラフィックを描くのであれば現状canvas要素以外の選択肢はない.美しい映像効果を必要とするゲームや複雑なグラフ等はcanvas要素を用いたほうが自由に作り込める分有利である.

コードの難読化からの考察

svgがdomとしてブラウザ上に展開されてしまう点についてはもう少し考慮する必要がある.昨今のwebブラウザでは標準的にdomツリーの構造を展開する機構が搭載されており,現在表示しているページの内部を容易に解析することが出来る.つまり,svgで構築されたアプリケーションをブラックボックス化するのは困難ということである.javascriptで全ての要素を動的に出力したとしても,その結果として得られた図形はユーザーに対して丸裸と言って良い.スクリプトを難読化してもほとんど効果はない.一方でcanvas要素を用いた場合は描画処理の全てがjavascriptに集約されるため,スクリプトコードを難読化するだけでもかなりの部分を隠すことが出来る.得られた画像も単なるラスタ画像であるため,内部の構造を辿るのは困難(不可能ではない)だ.

従って過信は禁物だが,コードの内容そのものに価値があり,内容を改ざんや盗み見から保護したい場合にはcanvas要素に分があると言える.一方svgはアニメーションをはじめとした画像処理を簡単に行えるため,企業ロゴやバーナー等のカジュアル用途に適している.

なお,(トランザクション処理を含むような)高いセキュリティが要求されるケースにおいてはhtmlアプリケーションと同様,クライアントサイドのみでの対処は不可能であり,サーバーサイドとも絡めた全体的な設計が必要となるのは言うまでもない.

上記を踏まえるとそれぞれ得意とした分野が有ることに気がつくだろう.排他的にどちらを選択するというのではなく,適材適所で使い分けるのが理想的である.

html+css3によるグラフィック描画との考察

webブラウザ上でグラフィックを描く方法としては,canvas要素やsvgを用いる他にもhtml要素をcssで装飾して行う方法がある.cssもlevel3になってからは表現力(角丸やグラデーション,影等)が格段に向上したため,無理にsvgを使わなくてもhtmlだけである程度のグラフィックを描画することが可能となってきた.従って今後グラフィックを描く際,cssを用いるべきか,svgを用いるべきか迷うケースが出てくることだろう.

このような場合,描きたいグラフィックが「単体でグラフィックとして存在しうるもの」か,「コンテンツを装飾するもの」かを考えてみると良い. htmlは元来「文書」を表すものとして流通しているため,そこに含まれる要素は文書の構造を表している.従って,div要素等を重ねあわせて一つの絵を表すといった使い方は(技術的には興味深いものの)cssが無効となっている環境において何を表しているか判らない.この用途には本来svgを用いるべきであって,svgではグラフィックが表示されなくても,少なくとも画像を表していることは判別することができる.一方文章の装飾に関わる部分をいちいちsvgで記述するのはsvgの特性(レイアウトが固定となりがち)から言っても現実的でない.この場合は素直にcssを用いると良い.

とは言ってもsvgは未だこなれていないため,いつどのような不具合が発生するかわからない.よって習熟に時間がかかりそうなsvgよりも長年のノウハウが蓄積されたhtml+cssを選択するのも仕方がない.が,個人的には折角svgという選択肢が増えたのだから,ぜひとも使ってみて欲しいところである.もちろん今直ぐ全てをsvgで書き換えろなんて言っていない.ピンポイントで必要な部分に必要な分だけsvgを用いれば良い.幸いなことにhtmlからsvgを利用する方法は多数存在しているので,既存環境への改変を抑えつつ少しずつ導入していくことで次第にノウハウが蓄積していくことだろう.

svgとセキュリティ

ここまではsvgとしての役割と特徴について考えてみた.svgが様々な場面に応用可能な文書形式であることが判ったことだろう.その一方でsvgが高機能であること自体が新たなセキュリティリスクを生ずる.ここではsvgを扱う上でセキュリティの面から見た注意点について考えてみよう.

静的な画像形式としての誤解

svgは動的な画像形式という独特な考え方をするため,一般のラスタ画像を代表とする静的な画像形式とは一線を画している.その一方で一般ユーザーのもつ「画像ファイル」=「静的なファイルフォーマット」=「安全」と言った思い込みがsvgにも適用されてしまう可能性がある.その為,問題のあるコードを含むsvg文書がその危険性が認識されないまま拡散するケースも発生しうる.

危険部位を削除した上での配布

よって不特定多数からsvg画像を収集するようなシステムを検討する場合は,その内部に問題のある内容が含まれていないか確認すべきである.通常このような仕組みをとる場合,主眼となる対象はグラフィックであり,スクリプト処理は必要ないはずである.従ってスクリプトに関わる部分を思い切って削除してしまうと言った方法が有効と思われる.危険な部分を削除し,安全な範囲でsvgファイルを提供するようにするのだ.
※もちろん,これだけでは十分な対策とは言えない.

htmlとの類推による対策

svgはスタイルシートやスクリプトを使えるなど,立ち位置としてはhtmlと非常によく似ている.従って,一般的に行われているhtml文書における(サーバーサイド・クライアントサイド)のセキュリティ対処策をそのままsvgに適用することが可能であろう.つまり,xssやxsrf等の考え方はsvgにおいてもそのまま通用すると考えて良い.

svgの参照モードを利用する

svgは参照モードと呼ばれる仕組みによって利用場面によって有効となる機能が変化する.従ってより制限の大きいモード下でsvgを表示することで,危険なコードが実行されることを防ぐことができる.

svg機能を静的に分離する

svgのもつ仕組みには魅力的なものが多く,様々な機能を組み合わせて高機能なエクスペリエンスを提供することができるだろう.だが,既存のhtmlだけで完結していた世界がインラインsvg等の新たに追加された内容により,組み合わせ爆発的な非常に複雑な構成となってしまった.これを更に動的に作り出すといった場合,未知の事象を招く可能性を否定できない.
従って,svgが担当する部分はsvg文書として単独で存在しうるようにしておき,動的に変化させる部分を必要最低限に抑えることで,svgの動作を想定の範囲内に留めることが可能となる.svgにはグラフィック部品を定義する様々な方法が提供されている.

何れにせよsvgに関わるセキュリティの検討は始まったばかりであり,今後新たな脅威が発生するとも限らない.常に最新の情報を収集し,いざという時にも適切な対策を採れるように意識しよう.