.style0 { color: #f26522; border-bottom-color:#f26522;margin-right:12px; } .style1 { color: #f26522; } .style2 { clear:both;height:0px; } .style3 { height:0px;clear:both; }
scriptjunkie{}
HTML5 と SVG でゾンビの黙示録を生き延びる
Justin Whitney | 2013 年 1 月 16 日
HTML5 を採用するブラウザーが急ピッチで増え続ける中、センスが良く、応答性の高い UI を作成するために開発者が利用できる選択肢も増えています。たとえば、スケーラブル ベクター グラフィックス (SVG) であれば、これまでの機能が刷新され、非常に洗練されています。
SVG 仕様が登場したのはかなり前のことです。この仕様 (正確には一連の仕様) は 1999 年から検討が続いており、ベクター グラフィックスの XML ベースのファイル形式を規定します。SVG ブロックは、ベクター画像を構成する個々の要素、つまり、パス、図形、塗りつぶし、ストロークといった特性を定義します。Adobe Illustrator や Inkscape で作成してからラスター形式にエクスポートするような特殊なグラフィックスでも、SVG により軽量のオプションが提供されます。また、SVG では実行時に画像を操作する際に利用できる機能も数多く実現できる見込みがあります。これは、SVG の "スケーラビリティ" を示す部分です。
HTML5 標準が幅広く採用されるようになれば、ブラウザーでの SVG は新たな方向に向かいます。たとえば、インライン SVG 用の <svg> タグが重要になります。SVG のスタイルを CSS を使って設定するようになります。クライアント側で JavaScript を使って SVG 画像の作成や操作を行うような、DOM の新しい使い方が可能になります。
今回の連載は、人類に 2 つのメリットをもたらすことを目的にしたチュートリアル形式のデモ シリーズです。最初のメリットとして、各ブラウザーの SVG 導入方法の違いを示しながら、複数のブラウザーと互換性のある SVG の例を取り上げます。2 つ目のメリットとして、人間がゾンビの黙示録を生き残れる確率をほぼ正確に予測します。
手順 1: 準備
作業を始める前に、ターゲットにするブラウザーを把握しておくと役に立ちます。最新のブラウザーはすべて SVG をある程度採用していますが、その実装には小さなものから大きなものまで多く違いがあります。たとえば、同期マルチメディア統合言語 (SMIL) 仕様では、<animate> 要素を使って SVG をアニメーションで動かす方法が規定されています。この要素を使えば、開発者は <svg> 要素だけを使用して、ユーザーと対話操作を行いながら、個別の属性を時間の経過とともに変化させることができます。残念ながら、SVG/SMIL アニメーションをまだ認識しないブラウザーもあります (ただし、SVG アニメーション の代替形式が存在します)。
こちらのサイト (http://caniuse.com/、英語) では、すべての主要デスクトップ ブラウザーとモバイル Web ブラウザーが細かく相互比較され、さまざまな HTML5 機能をどのバージョンが認識するかが示されています。特に便利なのが、インライン SVG (英語) や SVG フィルター (英語) (Internet Explorer 10 に追加されたばかり) の利用など特定の SVG 機能のページです。
手順 2: SVG 要素の作成
今回作成する SVG ゾンビの黙示録生き残り予測ツールでは、「都市」を表すペイン、リスク要因を制御するパネル、予測メーター自体を表すペインという 3 つの独立した SVG 要素を使用します。
まず、"cityBox" という 600 x 400 のルート要素を作成します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Planning for the Zombie Apocalypse with HTML5 and SVG</title>
<script>
</script>
<style>
</style>
</head>
<body>
<svg id="cityBox" width="600" height="400">
</svg>
</body>
</html>
これだけです。表示されないボックスの完成です。これは冬のゾンビーランドです。ボックスの境界線には CSS を使ってスタイルを追加できます。これには、<svg> 要素自体の "style" 属性を使用するか、次のようにヘッダーでスタイルを定義します。
<style>
#cityBox {
border: 1px solid #000000;
float: left;
}
</style>
手順 3: テキストの追加
開発者はページ上のテキストをさまざまな方法で制御できますが、SVG を使ってテキストを制御すると、文字オフセットの変更、テキストの拡大、文章の回転、パスに合わせたテキストの調整など、多くの興味深いオプションを利用できるようになります。
ただしその前に、cityBox 要素にタイトルを追加します。
<svg id="cityBox" width="600" height="400">
<text x="300" y="50">
Surviving the Zombie Apocalypse
</text>
</svg>
図 1 <text> 要素を含む SVG 要素
x 座標と y 座標は先頭文字の基準位置を定義します。この例から座標指定を取り除くと、テキストは SVG 要素の上辺に移動し、一部が見えなくなります。
SVG <text> 要素のスタイルを設定する場合、"style" 属性、定義済みスタイル、または個別の SVG 属性という 3 つの方法を利用できます。ただ、使用する手法とブラウザーによっては、特定の属性の動作が不適切になるようです。たとえば、"font-family" の定義は、どこで使用してもすべてのブラウザーで機能します。しかし、"font-size" の実装には一貫性がありません。<style> ヘッダーで "font-size" を定義すると、Chrome でも Internet Explorer でも機能しません。次の例のように、<text> 要素の "style" 属性で "font-size" を定義すると、Chrome では機能しますが Internet Explorer では機能しません。
<text x="300" y="50" id="titleText" style="font-size: 36;">
どちらのブラウザーでも機能する唯一の方法は、"font-size" を <text> タグ内の属性として定義する方法です。そこで、デモの目的を果たし、複数のブラウザーで最大限に互換性を確保するには、以下のように定義します。
<text x="300" y="50" font-family="sans-serif" font-size="36"
text-anchor="middle" stroke="#000000" fill="#000000">
CSS 同様、ストロークの色と塗りつぶしの色には色名も 16 進値も使用できます。"text-anchor" 属性にも注目してください。この属性は、原点の x、y 座標との相対でテキスト位置を定義します。既定値は "left" なので、この例では "middle" に設定し、原点が <svg> 要素の中心になるよう定義しています。
ここで、"text-anchor" とテキストについて一般的に見られる興味深い動作をもう 1 つ紹介します。<text> 要素が <svg> 要素の境界を超えると何が起こるかはブラウザーによって異なります。Chrome では、<svg> 要素の境界を超えた部分は切り捨てられます。しかし、Internet Explorer では、テキストが <svg> 要素の境界を超えて表示されます。
他のベクター画像同様、SVG テキストにはストロークも塗りつぶしも指定できます。既定では、<text> 要素は、ストロークのない黒色の塗りつぶしで表示されます。今回の例では、黒色のストロークを追加しています (図 2 参照)。テキストを太くするだけでなく、興味深い効果を生み出すために、ストロークの色をアニメーションで変化させることもできます。これについては、連載の後半で説明します。
図 2 書式設定した <text> 要素
手順 4: 画像
SVG のポイントは表向きにはグラフィックスの作成ですが、グラフィックスをゼロから作成するより、既存の SVG グラフィックスをページに組み込む方が効率が良い場合があります。Microsoft Expression Design、Adobe Illustrator、Inkscape などのベクター デザイン ソフトウェアでグラフィックスを作成する場合、または ウィキメディア コモンズ (英語) のような SVG クリップ アート ライブラリから入手する場合には特にこのことが当てはまります。
ゾンビの黙示録生き残り予測ツールの都市ペインの最終形では、ゾンビの黙示録のすべての要素を表示する予定です。しかし、今回は人間を 1 人だけ用意することから始めましょう。恐怖にかられ、死に物狂いで逃げる 1 人の人間です。まず、元になる人間を Inkscape で作成して、SVG ファイル (human.svg) として保存します (注: このチュートリアルで使用する .svg グラフィックス ファイルはすべて http://openclipart.org (英語) で提供されているもので、ダウンロード可能です)。
<image> 要素が機能する方法には、複数のブラウザーがサポートする方法と、ブラウザーによってはサポートされない方法があります。
最初は最も簡単な方法で、<svg> 要素内に次のコードを追加します。
<image id="human" x="275" y="175" width="50" height="50" xlink:href="human.svg" />
このタグは、SVG ファイル ("human.svg") への外部参照を追加し、画像を座標 (275, 175) に配置します。この座標は、画像のサイズを考慮した後の都市の中心になります。画像のサイズは 50 x 50 にスケールを変更しています。今回の場合、オリジナルのファイル サイズを把握する必要はありません。画像の最大サイズがパラメーターに指定した値と一致するよう自動変換され、その他のサイズはこれに比例してスケール変換されます。結果は図 3 のようになります。
図 3 Chrome でスケールが自動変換された SVG 画像
残念ながら、必ずしもこのようになるわけではありません。Firefox や Internet Explorer など多くのブラウザーでは、width 属性と height 属性が定義するのは画像サイズではなく表示領域なので、結果は左上隅の座標を起点とするクリッピングされた画像になります (図 4 参照)。
図 4 Firefox や Internet Explorer でスケールが自動変換された SVG 画像
これを解決する方法は 2 つあります。1 つは画像自体を編集する方法で、画像を目的のサイズに変更します。しかし、これでは拡張性の高いグラフィックスを使用するという目的が損なわれます。そこで、もう 1 つの方法として変換を適用します。
テキスト エディターで "human.svg" ファイルを開き、メタデータに含まれる現在の画像サイズを表示します。今回の場合は次の値でした。
width="342.70523"
height="482.82114"
ただし、これらの属性を手動で編集すればすべてがうまくいくとは思わないでください。それほど簡単ではありません。幅や高さのメタデータが変化すると、SVG ファイルに埋め込まれている残りの XML データにより、画像マスクが予期しない動作をします。どのような動作になるかはブラウザーによって異なります。
そのため、この幅と高さの値を使用して、新しい <image> 要素を作成します。
<image id="human" x="2750" y="1750" width="343" height="483" transform="scale(.10,.10)"
xlink:href="human.svg" />
今回の例では、幅と高さを画像の実際の値 (概数) に設定します。最大サイズ (高さ: 483) を 10% に縮小して、50 x 50 に近い画像を作成します。ただし "transform" 属性は要素の原点にも影響します。そこで、元の座標 (275, 175) を (2750, 1750) に変更して、同じ位置を維持する必要があります。(2750, 1750) は、元の値を 10% の倍率で割った値です (275 / 0.1 = 2750)。これを Internet Explorer で表示すると図 5 のようになります。
図 5 transform=scale を適用した <image> 要素の Internet Explorer での表示
これで、パニックに陥った小さな人間がすべてのブラウザーで同じように表示されるようになります (少なくともこのチュートリアルをテストしたすべてのブラウザーで同じように表示されます)。
手順 5: 基本図形
これで、環境が整いました。ここからは少し複雑にしていくため、基本に戻り、SVG のほとんどのチュートリアルで最初に取り上げられるシンプルな図形を制御パネルに作成します。SVG では、いくつか図形要素 (<line>、<rect>、<circle>、<ellipse>、<polygon>、および <polyline>) が定義されています。<path> 要素を使用して、まったく新しい図形を作成することも可能です。
予測制御パネルは、数量を変化させる三角形の "ステップ" コントロール、テキスト ラベル、および画像が中に表示された 2 つの円で構成します。まず、<svg> 要素とそのスタイル (現時点では開発目的で 1 ピクセルの境界線を持つスタイル) を作成します。
<style> の下に、次のコードを追加します。
#controlPanelBox {
border: 1px solid #000000;
float: left;
}
ページの <body> に次のコードを追加します。
<svg id="controlPanelBox" width="400" height="400">
</svg>
三角形は、<polygon> 要素でも <path> 要素でも作成できます。見た目はまったく同じになります (図 6 参照)。
<polygon points="50,50 100,25 100,75" stroke="black" stroke-width="1" fill="red" />
<path d="M 50 50 L 100 25 L 100 75 L 50 50" stroke="black" stroke-width="1" fill="red" />
図 6 <polygon> (左) と <path> (右)
<polygon> 要素では、多角形の各頂点を絶対値で定義します。作成される図形は自動的に塗りつぶされます。<path> 要素では、原点をデータ ("d") 属性で moveto ("M") 値として定義します。この指定に続いて lineto ("L") で示す各点に向かってパスを描き、最後に原点に戻ります。この最後の点でパスを閉じ、多角形を作成します。原点に戻らなくても、三角形は赤く塗りつぶされますが、最後の辺のストロークは描画されません。
パスの便利な使い方の 1 つとして、M (moveto) と L (lineto) を小文字にするだけで相対値を指定できます。その結果、M 値を変化させることにより、パスを簡単に描けるようになります。たとえば、次の 2 つの要素はまったく同じ図形 (図 6 とも同じ図形) になります。
<path d="M 50 50 L 100 25 L 100 75 L 50 50" stroke="black" stroke-width="1" fill="red" />
<path d="M 50 50 l 50 -25 l 0 50 l -50 -25" stroke="black" stroke-width="1" fill="red" />
このため、一般には <plygon> 要素の方が作成は簡単ですが、今回の制御パネルの場合は相対パスの方が合理的です。制御パネルには複数の三角形を使用するため、2 つのバージョン (同じ形で向きが異なる画像) を作成してからコピーし、M 値を変えるだけで、別の場所に表示します。
コントロールの各セットには、ラベルやテキスト フィールドとして機能する 2 つの <text> 要素も用意します。テキスト フィールド用の <text> 要素は、JavaScript を使ってコントロールの操作に応じて値を変化させます。これについては連載の後半で取り上げます。
制御パネルの最初のパラメーターは都市の人口を表し、要素のセットは次のようになります。
<path id="zombieLess" d="M 50 50 l 50 -25 l 0 50 l -50 -25"
stroke="black" stroke-width="1" fill="red" />
<text id="zombieLabel" font-size="15" font-family="sans-serif"
text-anchor="middle" fill="red" x="175" y="25">
City Population (000s)
</text>
<text id="zombieText" font-size="25" font-family="sans-serif"
text-anchor="middle" fill="black" x="175" y="60">
0
</text>
<path id="zombieMore" d="M 300 50 l -50 -25 l 0 50 l 50 -25"
stroke="black" stroke-width="1" fill="red" />
図 7 都市の人口コントロールを配置した controlPanelBox 要素
さらに、要素をグループ <g> 要素内に入れ子にすることができます。グループ全体に名前を付け、そのグループにスタイルを設定して操作すると、グループ内の各メンバーに設定が適用されます。今回は、各コントロールを整理するためだけにグループを使用します。
相対パス定義を使い、簡単なコピーと貼り付けの操作でまったく同じ 2 つのコントール セットを作成してから、moveto の点、<text> の原点、ID、およびテキスト コンテンツを変えて、ページ上に 3 つのステップ コントロールを作成します。
<g id="zombieGroup">
<path id="zombieLess" d="M 50 50 l 50 -25 l 0 50 l -50 -25"
stroke="black" stroke-width="1" fill="red" />
<text id="zombieLabel" font-size="15" font-family="sans-serif"
text-anchor="middle" fill="red" x="175" y="25">
City Population (000s)
</text>
<text id="zombieText" font-size="25" font-family="sans-serif"
text-anchor="middle" fill="black" x="175" y="60">
0
</text>
<path id="zombieMore" d="M 300 50 l -50 -25 l 0 50 l 50 -25"
stroke="black" stroke-width="1" fill="red" />
</g>
<g id="mallGroup">
<path id="mallLess" d="M 50 150 l 50 -25 l 0 50 l -50 -25"
stroke="black" stroke-width="1" fill="red" />
<text id="mallLabel" font-size="15" font-family="sans-serif"
text-anchor="middle" fill="red" x="175" y="125">
# of Shopping Malls
</text>
<text id="mallText" font-size="25" font-family="sans-serif"
text-anchor="middle" fill="black" x="175" y="160">
0
</text>
<path id="mallMore" d="M 300 150 l -50 -25 l 0 50 l 50 -25"
stroke="black" stroke-width="1" fill="red" />
</g>
<g id="redneckGroup">
<path id="redneckLess" d="M 50 250 l 50 -25 l 0 50 l -50 -25"
stroke="black" stroke-width="1" fill="red" />
<text id="redneckLabel" font-size="15" font-family="sans-serif"
text-anchor="middle" fill="red" x="175" y="225">
Rednecks
</text>
<text id="redneckText" font-size="25" font-family="sans-serif"
text-anchor="middle" fill="black" x="175" y="260">
0
</text>
<path id="redneckMore" d="M 300 250 l -50 -25 l 0 50 l 50 -25"
stroke="black" stroke-width="1" fill="red" />
</g>
図 8 相対 <path> 要素による controlPanelBox 要素
コントロールの最後のセットは、すべての図形の中で最も基本的な円を使用します。<circle> 要素は、3 つの主要属性として中心の x 座標 ("cx")、中心の y 座標 ("cy")、半径 ("r") を定義することで機能します。既定の塗りつぶしは黒でストロークは描かれません。ただし、今回はストロークを描きます。
今回はトグル コントロールなので、現在の選択されている円を赤の太いストロークで、選択されていない円を黒の細いストロークで描くようにします。どちらの円も白で塗りつぶし、ゾンビの画像を保持できるようにします。
<circle id="slowCircle" cx="75" cy="325" r="40" stroke="red"
fill="white" stroke-width="4" />
<circle id="fastCircle" cx="275" cy="325" r="40" stroke="black"
fill="white" stroke-width="2" />
図 9 ゾンビの円
ゾンビの画像は、人間の画像と同じ方法で処理します。サイズはグラフィックスの実際のサイズとして定義し、"transform" 属性を適用して元のサイズの 0.16 倍に縮小します。この倍率を原点の x 座標と y 座標にも適用します。また、SVG 要素は順番にレンダリングされるので、この画像は円の後に描画する必要があります。
<circle id="slowCircle" cx="75" cy="325" r="40" stroke="red"
fill="white" stroke-width="4" />
<image id="slowZombie" x="375" y="1875" width="175" height="304"
transform="scale(.16,.16)" xlink:href="zombie.svg" />
<circle id="fastCircle" cx="275" cy="325" r="40" stroke="black" fill="white" stroke-width="2" />
<image id="fastZombie" x="1630" y="1875" width="175" height="304"
transform="scale(.16,.16)" xlink:href="zombie.svg" />
図 10 ゾンビを含むゾンビの円
最後に、ラベル フィールドとテキスト フィールドのペアを追加し、全体をグループにします。
<g id="speedGroup">
<circle id="slowCircle" cx="75" cy="325" r="40" stroke="red"
fill="white" stroke-width="4" />
<image id="slowZombie" x="375" y="1875" width="175" height="304"
transform="scale(.16,.16)" xlink:href="zombie.svg" />
<text id="speedLabel" font-size="15" font-family="sans-serif" text-anchor="middle"
fill="red" x="175" y="315">Zombie Speed</text>
<text id="speedText" font-size="25" font-family="sans-serif" text-anchor="middle"
fill="red" x="175" y="350">Slow</text>
<circle id="fastCircle" cx="275" cy="325" r="40" stroke="black"
fill="white" stroke-width="2" />
<image id="fastZombie" x="1630" y="1875" width="175" height="304"
transform="scale(.16,.16)" xlink:href="zombie.svg" />
</g>
この時点のゾンビの黙示録生き残り予測ツールは図 11 のようになります。
図 11 (現時点での) ゾンビの黙示録生き残り予測ツール
今後の展望
現状では、この予測ツールを使用する全員が生き残れないのは明らかです。完全には死なくてもゾンビになるかもしれません。それとも、ただ餌食になるかです。連載の次回は、今回開発した既存のコントロールを土台にして、予測メーターのペインや、ボタンを押せば処理が行われるようにアニメーションと JavaScript をいくつか追加します。パート 2 (こちら) をお楽しみに。
現時点のプロジェクトは次のリンクから確認できます。
http://justinwhitney.com/zombies/zombies_part1.htm
SVG の例については以下の資料をご覧ください。
SVG ダイス (英語)
SVG グラデーションの背景作成ツール (英語)
Internet Explorer 10 での SVG フィルター効果 (英語)
SVG ヘリコプター (英語)
執筆者紹介
Justin Whitney はテキサス東部の田舎町で文明の終焉に備えながら、Web サイトとモバイル アプリをビルドしています。