日記
SVG の昔と今
先日行われた Sugamo.css で発表した内容を少し手直しして、SVG の成り立ちと現在について、The Secret Origin of SVG などを参考にしながらまとめてみました。
SVG の昔
Web ができてまもない頃、HTML の拡張や類似形式が流行しましたが、その中でもベクターグラフィクス言語は Web で役に立つことはわかっていました。そこで、1996年、W3C は「オープンで、リンクやメタデータ付けができて、クロスプラットフォームで開発できる」ベクターグラフィックス描画言語を募集しました。1998 年までには以下の 5 つの規格に落ち着きました。
- PGML
- VML
- HGML
- DrawML
- WebCGM
PGML (Precision Graphics Markup Language)
Adobe の PostScript や PDF を元に開発された 2D スケーラブルグラフィックスマークアップ言語で、IBM, Netscape や Sun Microsystems も賛同していました。PGML には次のような特徴があります。
- モーションパスなどのシンプルなアニメーションが可能
- CSS が有効
- PDF に変換が容易
- Adobe Illustrator との連携する予定もあったらしい
参考 : PGML Q & A
PGML は次のような書式でマークアップします。
<?xml version="1.0"?>
<!DOCTYPE pgml SYSTEM "pgml.dtd">
<pgml>
<group>
<rectangle x="100" y="100" width="100" height="100" />
<rectangle x="300" y="100" width="100" height="100" />
</group>
</pgml>
上記のコード中にもある x, y, width, height 属性などの座標系や、変形、色空間は、後に登場する SVG の仕様に影響を与えます。
VML (Vector Markup Language)
Microsoft, Macromedia, Hewlett-Packard などから提案された 2D スケーラブルグラフィックスマークアップ言語でもともとは PowerPoint のシェイプなどで利用されていいました。VML は ActiveX を経由して IE5 以降で利用可能です。
- TIME と組み合わせることでアニメーションが可能
- CSS が有効 (座標や大きさは CSS で指定する)
VML は次のような書式でマークアップします。
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<title>VML</title>
<style>
v\:rect{ behavior: url(#default#VML); position:absolute; /zoom:1;}
v\:group{position:absolute;}
</style>
</head>
<body>
<v:group>
<v:rect style="top:100px; left:100px; width:100px; height:100px;" />
<v:rect style="top:300px; left:100px; width:100px; height:100px;" />
</v:group>
</body>
</html>
VML は上記のコード中にもあるグルーピングのための group や矩形描画のための rect の他にも、楕円、円弧、パス(ベジェ曲線) などの要素型があり、この要素型の種類は後に登場する SVG の仕様に影響を与えます。
HGML (Hyper Graphics Markup Language)
(回線が細い) モバイルのデバイスで帯域節約をしながら画像を表示するための規格です (OBML みたいな ?)。Drawing Primitives (楕円や矩形) 描画、image manipulation (画像操作と変形)、Themes (CSS のような仕組み) の 3つの機能で成り立っています。
e.g.
<hgml>
<rectangle coords="100,100,200,200", style="dotted">
<rectangle coords="300,100,400,200", style="dotted">
</hgml>
DrawML
技術的な図版を作成するための 2D スケーラブルグラフィックスマークアップ言語です。作成とメンテナンス性を重視して単純な設計になっており、要素型は 5種類のみ (type 属性で楕円や矩形の描画を分ける) で、グラフィカルな表現には不向きです。
e.g.
<drawml>
<shape type="rectangle" x="100" y="100" width="100" height="100"></shape>
<shape type="rectangle" x="300" y="100" width="100" height="100"></shape>
</drawml>
WebCGM (Web Computer Graphics Metafile)
CGM の Web 版で、その名前の通り、リンクを重視したグラフィックス表現の形式です。ここまでに挙げた他の規格とは違い、WebCGM1.0 はマークアップ言語ではありません。
SVG のすこし昔
SVG1.0 は VML と PGML を統合し、CSS や XLink を追加した 2D スケーラブルグラフィックスマークアップ言語として、2001 年に勧告されました。
SVG は特別なプラグインや独自フォーマットが不必要な画像形式で、次のような特徴を持っています。
- 画像形式である。GIF や JPEG のように画像を表示可能
- スケーラブルである。ベクトルデータなので拡大/縮小しても画像が劣化することはない
- XML である。バイナリーデータではないのでテキストエディタでもある程度編集すことが可能
- 単純な原始図形 (矩形や楕円など) や 2次、3次ベジェ曲線によるパスデータで図形を描画する
- 非破壊のフィルター、マスク、クリッピング表現が可能
- アニメーション (SMIL) による表現が可能
- JavaScript が有効です。(ただしHTML への埋め込み方法によっては JS は無効)
SVG は VML の要素型、 PGML の座標系指定を組み合わせたようなコードを書きます。
<?xml version="1.0"?>
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<g>
<rect x="100" y="100" width="100" height="100" />
<rect x="300" y="100" width="100" height="100" />
</g>
</svg>
- 上記の demo
しかし、残念なことに Web ブラウザーによる実装がなかったため、勧告されてから最近 (2010年くらい) までは、Web 上であまり使われませんでした。SVG はモバイルの分野では利用されていたようです。
SVG の今
最近になって SVG を利用する準備が整いつつあり、再注目されています (…たぶん)。
モバイルデバイスでのブラウジングにも力を入れる Opera は早くから SVG を実装していましたが、最近では、Firefox や Webkit 系でも SVG 実装はかなり進んできた。また IE9 でも SVG1.1 のほとんどのスペックを実装予定です (ただし、IE9 は Filter, Fonts, Animation の実装予定はありません)。
また、モバイル Safari では SWF を再生できませんが、アニメーションを含む SVG を表示可能です。
さらに、HTML5 では svg 要素型が登場する予定で、text/html に SVG の語彙を混在させることもできるようになります。
SVG の利用シーン
SVG は HTML と親和性の高く、図形を描画する画像としてだけでなく、DOM 操作、アクセシビリティの確保、メタ情報付け、リンクをも利用できる言語でもあります。そのため、将来の Web ページや、Web アプリケーション SVG の利用が期待できます。
例えば…
- ロゴ
- グラフ
- アイコンなどの装飾用パーツ
- 拡大しても劣化しない背景画像
- ボタン、スライダーなどの UI
- フローチャート
などが挙げられます。また、資産が SVG で管理されている場合もあり、その資産を利用することもできるかもしれません。
例えば…
- 地図
- 図面や設計図
などが挙げられます。
既存の IE を考えると SVG を利用しづらい
SVG を利用するうえで問題になるのが IE6 ~ 8 の存在です。IE が SVG を実装するといっても、次期バージョンの 9 であり、まだ正式版ではありません。IE はベクターグラフィックスマークアップ言語の規格として、これまで頑なに VML のみを実装していました。以前は IE 用の SVG 表示プラグインがAdobe から適用されていましたが。そのため今すぐには SVG を利用できないと考える人も多いのです。
しかし、ここまでの流れで SVG は VML の血を受け継いでいることを説明しました。つまり SVG ∋ VML に近い状態ということになるわけです。例えば SVG と VML のコードを抜粋して比べると以下のようになります。
SVG のコード断片
<g>
<rect x="100" y="100" width="100" height="100" />
<rect x="300" y="100" width="100" height="100" />
</g>
VML のコード断片
<v:group>
<v:rect style="top:100px; left:100px; width:100px; height:100px;" />
<v:rect style="top:300px; left:100px; width:100px; height:100px;" />
</v:group>
かなり似ていることがわかります。
フォールバックとラッパーで IE 6 でも SVG を
2010年 7月現在までの段階で、IE6 でも SVG を擬似的に表示することができ、そのための方法は大きく分けて 2つあります。ひとつは SVG のコードを VML や SWF に変換するフォールバックの手法、もうひとつはベクター画像を出力するための特別なコードを書き、結果 SVG または VML で出力するラッパーを使った方法です。
フォールバック用ライブラリー
- svgweb
- SVG を SWF 上に表示する。ただし、HTML のコードの書き方がやや微妙。個人的にはあまり…(独自のスクリプトタイプを利用してパースさせない仕組み)
- AMPLE SDK
- SVG を VML に変換して表示する。SVG Web と似たような HTML を書くことになる。(独自のスクリプトタイプを利用してパースさせない仕組み)
- SIE
- SVG を VML に変換して表示する。日本の方が作っている。パスのエッジが少し気になるので今後もうすこしきれいになると…
ラッパー用ライブラリー
- Raphael
- Raphael 用のコードを書くと SVG と VML に出し分ける。
これらのライブラリーを活用することで、IE 6 を含めた様々な Web ブラウザー上で今すぐにベクターグラフィックスを扱うことができます。スクリプトやアニメーションを複雑に利用している場合には表現しきれ無いかもしれませんが、グラフやロゴ程度の描画程度なら問題ないでしょう。
ここで挙げたライブラリーを試してみたこと、ひとまず Raphael が一番安定していて使いやすく感じました。(SVG のコード (リソース) をフォールバックして表示できるライブラリーもさらに安定して使いやすいものが出てくるといいなぁと思っています。)
マークアップ言語で図画やロゴを描く
最近、HTML と CSS を使い、Opera のロゴや、ドラえもん、アンパンマンを描画するといったネタをしばしば目にします。例えば HTML と CSS の表現力を利用すれば SVG のロゴを描画することもできます。
border-radius による角丸や transform による変形などを使えばいろいろな表現ができるようになりますが、一般的な CSS はあくまでも文書の装飾であり、図画の描画をするための技術ではありません。CSS のベンチマーク的にネタとして試す分には別にいいのですが…。
次に用意したのは前記のロゴを SVG を用いて描画した demo です。
- SVG を用いた SVG のロゴ (IE9、Opera, Firefox, Webkit 系で動作)
SVG とはベクターグラフィクスを描画するためのマークアップ言語 (XML) です。例えば円や矩形、ベジェ曲線の描画、グラデーションなどを利用することができます。Adobe Illustrator のデータに似ています。アニメーションもできるので Flash 4 くらいのことができます。現在は XHTML 内や、img 要素などの埋め込み対象として利用できます。また、HTML5 では <svg> 要素が登場し、より扱いやすくなる予定です。
e.g.
<head>
<title></title>
</head>
<body>
<h1>circle !</h1>
<svg>
<circle cx="50" cy="50" r="30" fill="#00f"/>
</svg>
</body>
CSS ばかりではなく、SVG に注目してみるのも面白いと思います。ここでは簡単な図画を例にしましたが、オーサリングツールを使えば虎とか Firefox のロゴを SVG で描画することもできます。
Raphaël を使う
SVG は IE6 の存在もあり、今すぐに実務で使うのは難しいです。いまベクターグラフィックスを描画したいなら Raphaël を利用するとよさそうです。
Raphael は JavaScript でコードを書くと自動でベクターグラフィックスとして出力してくれるライブラリです。コードの書き方は SVG と canvas の中間のような。SVG または canvas のどちらかを書いた経験があればすぐに書くことが出来るんじゃないでしょうか。
試しに Raphael を使用してみました。SVG から Raphaël に置き換える感覚は XML から JSON を書くみたいな。例えば、円を描くには
var paper = Raphael("testDiv", 600, 600);
paper.circle().attr({cx:100, cy:100, r:50, stroke: "none", fill:"#f00"})
とします。
- Raphaël を用いた SVG のロゴ (IE を含むほとんどの Web ブラウザーで動作)
しっかり IE6 でも描画されます (IE には VML として出力されます)。ただし、VML の仕様にあわせて text に transform が使えないなどの縛りがあります。
新宿プログラマーズカフェナイト : SVG ネタで LT に参加しました
新宿御苑前 IDC フロンティア 10F セミナールームで行われた新宿プログラマーズカフェナイトのライトニングトークに参加しました。
自分はあまり興味はもっていただけないだろうと思いつつも SVG をネタを語らせていただきました。
参加者の皆様、フロントエンドなネタに反応していただきありがとうございました。
- 使用したスライド : <SVG/> (PDF)
- 使用した demo (今のところ Firefox 3.6以上専用。)
- 使用しわすれた demo (スライダーのみ。IE 9 PP, Opera, Fx, Webkit で動作)
demo について
demo の見所を以下にまとめてみました。
- スライダーを SVG で再現
- canvas と違い、SVG は描いた図形一つずつが DOM として維持される。また、それらの図形にはイベントを登録することができる。なので UI のパーツなどに向いている。transform による傾きなども可能。
- HTML とシームレス
- Flash などと違い、HTML とシームレスに扱うことができる。HTML の中に SVG を書くこともできるし、foreignObject により、SVG の中に HTML を書くこともできる。この demo では、 SVG 中に video 要素および p 要素を表示している。なお、この demo では foreignObject に SVG Filter を適用することで、間接的に HTML の要素にも Filter 効果を適用できているが、Fx 3.6 からは HTML の要素にも SVG Filter を適用することができる。これについては以前 post した『SVG の filter, mask, clip を HTML の要素に適用する (Fx 3.5 用)』を参照していただきたい。
- SVG の Filter effect
- SVG には Filter という効果がある。これは SVG の CSS を使い、SVG の要素に適用することができる。SVG の Filter は原始フィルターの組み合わせにより実現することができる。これにより、応用で様々な効果を作ることができる。例えば、ドロップシャドウの場合、
- 自分のアルファチャンネルをコピー
- コピーしたアルファチャンネルをずらす
- コピーしたアルファチャンネルをぼかす
また、懇親会では引き続きライトニングトークとして SVG を HTML 上に表示する方法を 7 つ紹介させていただきました。これについてもまたの機会に post したいと思います。
やっぱり技術者の人の前で話すのおもしろいなぁ。いい経験になりました ! 開催側の方、そして hisasue さん、ありがとうございました !
Web Fonts で SVG Fonts を利用する
SVG Fonts は @font-face と font-famiry プロパティーを使い、SVG で定義した図形をグリフとして利用できる SVG の仕組みで、このことは Fonts – SVG 1.1 – 20030114 に書かれていています。最近では @font-face を使えば SVG の中だけではなく、HTML 文書内のテキストにも SVG Fonts を適用できるよになってきました…ので試してみました。
現状では OPERA と Webkit が対応しています。また、Firefox は 3.7 以降で対応するようです。
- demo (現時点では Webkit 系、OPERA のみで動作します)
結果を比較すると次の通り。
| OPERA 10.01 | Safari 4.0.3 | Chrome 3.0.195.33 | |
|---|---|---|---|
| 2文字以上の文字列へのマッピング | × 未対応 | ◯ 対応 | ◯ 対応 |
| 任意の文字の選択 | ◯ 可能 | × 不可能 | × 不可能 |
| 文字列のコピー | ◯ 可能 | ◯ 可能 | ◯ 可能 |
| 行内の横並べ | ◯ 可能 | ◯ 可能 | ◯ 可能 |
| 行内のリンク | ◯ 可能 | ◯ 可能 | ◯ 可能 |
| textarea など入力箇所 | ◯ 可能 | ◯ 可能 | ◯ 可能 |
| CSS の color | ◯ 有効 | ◯ 有効 | ◯ 有効 |
| CSS の font-size | ◯ 有効 | ◯ 有効 | ◯ 有効 |
| CSS の font-weight | × 無効 | × 無効 | × 無効 |
| CSS の letter-spacing | △ 不具合 | × 無効 | × 無効 |
| CSS の text-decoration | ◯ 有効 | ◯ 有効 | ◯ 有効 |
| CSS の text-shadow | × 不具合 | ◯ 有効 | × 無効 |
使い方や作り方など
CSS 側の準備
@font-face {
font-family: MyFont;
src: url(font.svg#myFont) format("svg");
}
p{font-family:MyFont;}
のようにごく普通に WebFonts を適用するためのコードを書くだけです。ただし、このとき、fotmat("svg") を指定しておかないと Opera 10 では表示できませんでした。
SVG 側でのグリフの定義
各グリフはSVG で
<glyph unicode="マッピングする文字" horiz-adv-x="横幅" d="パスデータ" />
のように定義し
<glyph unicode="あ" horiz-adv-x="300" d="M 0,0 L 0,100 L 100,100 L 0,0 z" />
<glyph unicode="い" horiz-adv-x="300" d="M 100,100 L 0,100 L 0,0 L 100,100 z" />
のように書きます。
マッピングする文字は1文字に限らず、複数の文字の連なりにもマッピングをすることができます。 この場合は単純に unicode 属性の値に複数の文字列を指定し、
<glyph unicode="三角形" horiz-adv-x="300" d="M 100,100 L 0,100 L 0,0 L 100,100 z" />
のように書きます。これならロゴなどにも使えそうですね。また、絵文字のようなこともできちゃいます。
ほかにも x height やアセンダーなどの設定も行えます。これならだれでもテキストエディターさえあればグリフをつくれますね !!
自分は Inkscape を使いグリフを作りましたが…。
ちなみにこのネタは 第 11回 Sugamo.css に持ち込むために作ったネタです。まだまだこっそりと続けていますよー。
その他参考リソース
- Opera Presto 2.2 と Opera 10 概観 – Opera Developer Community
- Mozilla SVG Update: SVG Priorities in Firefox 3 : Firefox 3 には実装されていない。3には間に合わなかった機能とされているみたい。
- UNICODE RANGE GENERATOR : Unicode Range を調べるのに便利
続 Firefox 3.6 の HTML5 パーサーを試してみた
HTML5 における svg 要素についてもう少し試してみました。
CSS を試した
CSS のセレクターに名前空間を明示したときの表示を試してみたところ、表示に反映されました。HTML5 での svg 要素は SVG 名前空間 (http://www.w3.org/2000/svg) の要素ということになっているようなので、HTML 上で名前空間を明示していなくても SVG 名前空間の要素として扱われるようです。
デモ (html5.enable が有効な Firefox 用)
SVG の a 要素を試した
SVG の a 要素を使うときには、合わせて xlink の href 属性を指定するのですが、その時どうなるのか…。例えば次のような HTML の断片で
<body>
<svg>
<a xlink:href="http://google.com">
<circle cx=50 cy=50 r=45 />
<text x=20 y=55>google</text>
</a>
</svg>
</body>
のように、xmlns:xlink="http://www.w3.org/1999/xlink を宣言しなくても、xlink:href とすることで動作しました。(ちなみに、このときの a 要素の有効範囲は circle 要素の円部分のみでその外はクリックしてもなにもおこりません。)
デモ (html5.enable が有効な Firefox 用)
よくわからないけど SVG でできることはそのままできるようです。
