XML の論考: SVG、そしてスクリプトを使わずに作成するスクリプト

未来のロケット科学者のための宣言型アニメーション

今、さまざまな形で力を発揮できる SVG (Scalable Vector Graphics) ブラウザーが主流になってきています。David による以前の SVG に関する記事の続編として、Dethe がアニメーション用のスクリプトやその他のスクリプト作成タスクの代わりとして宣言型マークアップを使用する方法を検討します。その過程のなかで、スクリプトを他の XML 方言の宣言型マークアップに置き換える場合についても簡単に説明します。一般的なスクリプト作成タスクを宣言型マークアップにすることで、面倒なボイラープレート・コードを作成する必要がなくなり、エラーが減り、スクリプトの意図に沿いやすくなることから、コード固有の側面に専念できるようになります。

Dethe Elza, Senior Technical Architect, Blast Radius

Photo of Dethe ElzaDethe Elza のお気入りの肩書は、チーフ・マッド・サイエンティストです。http://livingcode.blogspot.com/ に、主に Python と Mac OS X に関するブログを掲載している他、彼の子ども達のためにプログラムを作成しています。この記事に関するご意見、ご提案は大歓迎です。



David Mertz, Ph.D, Author, Gnosis Software, Inc.

Photo of David MertzDavid Mertz はオープン・スタンダードの大いなる信奉者で、口やかましい人に圧倒されることはあまりありません。経歴は http://gnosis.cx/dW/ で紹介されています。この記事、過去の記事、または今後の記事に関するご意見、ご提案は大歓迎です。彼の著書、『Text Processing in Python』を読んでください。



2011年 3月 09日 (初版 2005年 10月 25日)

2011年 3月 09日、編集者からの注記: 一部のブラウザーは SVG アニメーションをサポートします。記事の SVG アニメーションは、Adobe プラグインを適用した Microsoft Internet Explorer、Google Chrome、および Mozilla Firefox でテストしました。サンプル・アニメーションが最も適切な動作をしたのは Adobe プラグインを適用した Microsoft Internet Explorer です。Google Chrome では、アニメーションの一部が動作しました。「ダウンロード」セクションに、サンプル SVG ファイルが含まれる x-matters42-examples.zip、およびサンプル SVG ファイルを埋め込んだ HTML ファイルが含まれる x-matters42-html-examplefiles.zip を用意してあります。

SVG はかなり前から W3C 勧告となっていますが、Web で幅広く採用されるまでには至っていません。その一方で、Mozilla (Firefox)、Apple (Safari)、そして Opera のブラウザーのすべてがプラグインなしで SVG をサポートするようになった (あるいはサポートを予定している) 今、この状況は変わってくる可能性があります。Linux デスクトップの Gnome と KDE も、テーマ、アイコン、背景、ゲームに SVG を使用できるようになっています。これまで、SVG を表示するには Adobe プラグイン (「参考文献」を参照) を使用するのが主な方法となっていたので、私もこの方法を使ってサンプル・コードをテストしました。

SVG とは一体何なのでしょうか。そして、どのような場合に SVG を使用するのが適切なのでしょうか。SVG はこれまで PDF、PostScript、Flash、HTML と比較されてきましたが、あらゆる点でそのどれとも重なる部分はありません。SVG は複雑です。そのため人によって様々なものになり得ますが、その一方でテキスト形式 (Google が索引を付けられます) であり、XML (DOM で操作できます) であることには変わりありません。最も基本的なレベルで言うと、SVG はベクター・グラフィックスを記述するための XML 言語です。ベクター・グラフィックスとは、線を描画して表現された画像のことであり、ピクセルの描画によって表現されるビットマップ・グラフィックスとは対照的です。ただし、SVG はビットマップ、テキスト、さらには音声ファイルを含めることも、操作することもできます。その上、SVG では以下のことが可能です。

  • ノイズやその他のエフェクトをベクター画像またはビットマップ画像に適用する方法を記述することができます。
  • 複雑な色のグラデーションおよびパターンを指定することができます。
  • Web の他の部分へのリンクを提供することができます。
  • SVG をスクリプトにして変換、アニメーション化、およびスタイル設定することができます。
  • 多くの点でインタラクティブです。

私 (Dethe) はこの記事で、David が SVG について以前に書いた「XML の論考」の記事を引き継ぎ、SVG のアニメーションと双方向性について説明したいと思います。具体的には、宣言型のアニメーションと双方向性です。

注: この記事に記載する SVG 文書を表示するには、SVG ビューアーが必要です (「参考文献」を参照)。また、関連するすべての SVG ファイルが含まれる .zip ファイルをダウンロードすることもできます。

宣言型プログラミングの基礎

宣言型プログラミングとは言ってみれば、何を発生させたいかを、それを発生させる方法の詳細を心配することなく記述することです。宣言型プログラミングの一般的な例には、スプレッドシート、SQL、XSLT、そして Haskell などのプログラミング言語が挙げられます。宣言型と手続き型の構造を混在させたプログラミング言語には、Lisp と Python があります。XML 方言は、それぞれがフォームの妥当性検証 (XForms)、データ・マイニング (XQuery)、変換 (XSLT)、イベント処理 (XML Events)、アニメーション (SMIL (Synchronized Multimedia Integration Language)) を処理するための複雑で反復的な JavaScript に代わり、より宣言型の機能を組み込む傾向にあります。

SVG ではこれまで、動画や写真、そして音楽、テキストをリアルタイムで統合するための言語である SMIL (「参考文献」を参照) を採用し、拡張してきました。SVG での宣言型アニメーションの大半は、SMIL から直接 (SMIL 名前空間を使わずに) 取り込まれます。けれども、SMIL が持つさまざまな側面には SVG のコンテキストでは意味がないために省略されるものもあれば、拡張されるものもありました。SMIL は RealNetworks の RealPlayer、Apple の QuickTime、そして (XHTML+SMIL として) Microsoft の Internet Explorer で使用されています。SMIL は、これらの異なるメディア・フォーマットの、時間とイベントに応じた振る舞いを指定するためのツールです。

SVG が SMIL から継承する宣言型機能を使用することで、例えばグラフィックスを規定の時間、あるいは特定のイベントに応じてアニメーション化することができます。宣言できるアニメーションのタイプは 5 種類あり、多数のイベントを使ってアニメーションをトリガーすることができます。

それでは早速、具体的な例を紹介します。


空白の描画

最初の例では、この記事の以降の例で使用するキャンバスを作成します。私はこれから小学校時代に戻って、ロケットと UFO のスケッチを使用します。つまり背景となるのは、3 つのパンチ穴が開いた、罫線付きノートの単純な用紙です。この例ではアニメーションを使用しません。ただ単に、いたずら書きできるように小学校で使うノートのようなキャンバスをセットアップするだけです。この極めて単純な用紙は 1 つの svg 要素だけで構成されていて、この要素には直線パターンと小さな円を定義する短いセクションが含まれています。本体 (defs の外側) で、用紙全体を囲む長方形を描画し、この長方形全体を直線パターンで埋め尽くします。次に、定義した円を取得して 3 箇所に描画します。リスト 1 に、このノート用紙の SVG コードを記載します。

リスト 1. ノート用紙
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink" 
        width="100%" height="100%" fill="white">
    <defs>
        <pattern id="single_line" x="0" y="0" width="1" height="32"
                patternUnits="userSpaceOnUse" viewBox="0 0 1 32">
            <line x1="0" y1="32" x2="1" y2="32"
                stroke="lightblue" stroke-width="0.5"/>
        </pattern>
        <circle id="single_hole" width="28" height="28"
            cx="14" cy="14" r="14" 
            fill="white" stroke="black" stroke-width="0.5"/>
    </defs>
    <rect x="0" y="0" width="100%" height="100%" 
        fill="url(#single_line)" stroke="none"/>
    <use xlink:href="#single_hole" x="32" y="10%"/>
    <use xlink:href="#single_hole" x="32" y="50%"/>
    <use xlink:href="#single_hole" x="32" y="90%"/>
</svg>

この例をブラウザーで実行するには、サンプル・コード (「ダウンロード」の 01_paper.svg) をダウンロードしてください。SVG ビューアーがインストールされている場合は、ここをクリックすると例を表示することができます。


ロケット科学

2 番目の例は、定義に 1 つの path 要素を追加し、この要素を svg の本体で一度使用します (リスト 2 を参照)。追加する path 要素は、絶対座標の移動コマンド (Mx y) と線の描画コマンド (Lx y) からなります (相対座標を使用するコマンドは小文字になります)。d 属性には (Wacom 社製のタブレットを使用して収集した) 1,072 のコマンドが含まれるので、リスト 2 では簡潔にするために省略しています。完全なファイルとその見事な結果は、サンプル・コード (「ダウンロード」の 02_rocket_static.svg) で確認することができます。

リスト 2. ロケット (変更部分のみ)
<defs>
    [...]
        <path id="rocket" stroke-width="3" stroke-linejoin="round" 
            stroke-linecap="round" stroke="#4C4C4C" fill="white" 
            d="M23 8 L21 11 L21 11 L20 16 [etc...]"/>
</defs>
[...]
<use x="50%" y="50%" xlink:href="#rocket"/>

これまでのところ、このいたずら書きは、これが書かれている仮想の用紙と同じように静止していますが (図 1 を参照)、次の例でその様子は変わってきます。

図 1. ロケット
ロケット

この例をブラウザーで実行するには、サンプル・コードをダウンロードしてください。SVG ビューアーがインストールされている場合は、ここをクリックするとグラフィックを表示することができます。


打ち上げ

ついに、ロケットを動かす時が来ました。SVG に期待できる機能のうち、目標とする軌道を辿る機能と自動回転機能を披露するために、このロケットを旋回させます。この 3 番目の例で実際に使用するのは、この記事で説明する宣言型アニメーションの 1 つ目のタイプ、animateMotion 要素です (リスト 3 を参照)。

リスト 3. 飛行中のロケット船 (変更部分のみ)
<defs>
    [...]
    <path id="rocket2" transform="rotate(90)" [...]/>
    <path id="circle" stroke-width="4" fill="none" stroke="#000000" 
        d="M100 350 A300,300 0 1,1 700,350 A300,300 0 1,1 100,350"/>
</defs>
[...]
<use xlink:href="#rocket">
  <animateMotion rotate="auto" dur="30s" repeatCount="indefinite">
      <mpath xlink:href="#circle"/>
  </animateMotion>
</use>

defs 要素には、ロケットが旋回する円を定義する path 要素を追加しました。また、ロケットの定義には rotate 変換を追加しました。これは、ロケットが正しい向きで円を回るようにするためです。SVG では、画像が線を辿るときに常に線の接線方向を向くように、画像の向きを変えることができます。円を選んだ理由は、私の手書きの軌道では、接線の向きがガタガタになってしまうからです。タブレットで滑らかに手を動かせる人であれば、より良い結果を得られると思います。重要な点は、アニメーションが辿る線は、任意の軌道にできることです。また、単純な circle 要素ではなく、楕円孤を使った path 要素で円を作成していることにも注意してください。これは、ロケットが始めと終わりのある軌道を辿れるようにするためです。

この例をブラウザーで実行するには、サンプル・コード (「ダウンロード」の 03_rocket_moving.svg) をダウンロードしてください。SVG ビューアーがインストールされている場合は、ここをクリックするとアニメーションを表示することができます。


UFO の目撃

当然、ぐるぐる回るだけのロケットでは、そのうち飽きてきます。そこで、4 番目の例ではもっと面白い画面にするために、別世界からの訪問者として UFO を登場させることにします (図 2 を参照)。この例は、平凡な animate 要素とその兄弟の animateColor 要素を説明するには、ちょうどよい機会です。

図 2. 未確認飛行ベクター
未確認飛行ベクター

リスト 4 に、UFO を作成するために変更した内容をすべて記載します。

リスト 4. UFO (変更内容のみ)
<defs>
   [...]
    <g id="ufo">
        <path id="ufo-body" d="M0 50 A100 100
            0 0 0 100 50 L100 40 A100 100 0 0 0 0 40 z"/>
        <circle id="port-1" class="port" cx="25" cy="45" r="6"/>
        <circle id="port-2" class="port"  cx="50" cy="45" r="6"/>
        <circle id="port-3" class="port" cx="75" cy="45" r="6"/>
    </g>
    <path id="back-and-forth" d="M100 50 L700 50 z"/>
</defs>
<use xlink:href="#ufo">
    <animateMotion dur="50s" repeatCount="indefinite">
        <mpath xlink:href="#back-and-forth"/>
    </animateMotion>
    <animateColor xlink:href="#port-1" dur="10s"
        repeatCount="indefinite" attributeName="fill"
        values="red;green;blue;red" begin="ufo.load"/>
    <animateColor xlink:href="#port-2" dur="10s"
        repeatCount="indefinite" attributeName="fill"
        values="green;blue;red;green" begin="ufo.load"/>
    <animateColor xlink:href="#port-3" dur="10s"
        repeatCount="indefinite" attributeName="fill"
        values="blue;red;green;blue" begin="ufo.load"/>
</use>

[...]

タブレットを使って収集したコマンドから成る巨大なブロックを path 要素に追加しなくても済むように、defs には単純な SVG の弧と円からなる ufo を追加しました。さらに、UFO が前後に移動する際に辿る単純な線を描画するために path 要素を追加しました。最後の z によって軌道が終わるため、UFO は開始点まで引き返します。本体で使用する use 要素は今までよりも複雑になっていて、ここには 4 種類のアニメーション要素が含まれています。それは、ロケットで使用したような animateMotion 要素と、これに続く3 つの animateColor 要素のブロックです。面白いことに、animateColor 要素は ufo に直接適用されるのではなく (通常は、直接適用されます)、xlink:href 属性を使って UFO に 3 つある覗き窓のそれぞれをターゲットにしています。さらに、各 animateColor 要素を開始するタイミングは UFO のメイン要素のロードに関連付けました。

この例をブラウザーで実行するには、サンプル・コード (「ダウンロード」の 04_ufo.svg) をダウンロードしてください。SVG ビューアーがインストールされている場合は、ここをクリックするとアニメーションを表示することができます。


ロケット対 UFO

5 番目の例では、ユーザー操作を追加します。この場合に使用するのも同じく宣言型です。SVG は想定されるすべてのマウス・イベントをサポートするだけでなく、キーボード・イベントもサポートします。さらには特定のキー・イベントもサポートできるので、ここで追加するユーザー操作にはキー・イベントを用いることにしました。この例では、アルファベットの各文字のキーを押すと、ロケットが宇宙に向けて打ち上げられます (図 3 を参照)。今こそ、UFO に乗った侵略者から我が故郷の惑星を守る時です!

図 3. ミサイル防衛
ミサイル防衛

この例では、ロケットは旋回しないので、ロケット定義から transform 属性を削除するとともに、円の定義を削除します。defs には、これ以外の変更は必要ありません。この例でのアクションはすべて本体内にあり、テーマには 26 のバリエーションがあります (リスト 5 を参照)。

リスト 5. ロケット対 UFO (変更内容のみ)
<use xlink:href="#rocket" x="4%" y="85%" display="none">
    <set id="showa" attributeName="display" to="inherit"
        dur="5s" begin="accessKey(a)"/>
    <animate dur="5s" begin="showa.begin" attributeName="y" 
        from="600" to="-100"/>
</use>

バリエーションはすべて、前に定義したロケットを共通して使用しますが、バリエーションごとに異なる x 座標とアルファベットのキーボード・イベントが関連付けられます。ユーザーがキーを押すと、set 要素がトリガーされ、それによってロケットが画面下部に表示されます。平凡な animate 要素がどのように set イベントの開始に関連付けられているかに注目してください。これを見ると、イベントが他のイベントをトリガーする方法がわかるはずです。連鎖したイベントが必要な場合には、set イベントの開始ではなく、終了によって次のイベントをトリガーすることができます。

この例をブラウザーで実行するには、サンプル・コード (「ダウンロード」の 05_rocket_defense.svg) をダウンロードしてください。SVG ビューアーがインストールされている場合は、ここをクリックするとアニメーションを表示することができます。ロケットの動作をトリガーするには、文字キーを押す必要があります。お使いのコンピューターの処理速度によっては、ロケットが登場するまでに多少の時間がかかる場合もあります。


小惑星の中を抜ける

SVG で宣言型アニメーションのスクリプトを作成する方法を見て回るこのツアーは、最後の animateTransform 要素の例で締めくくります。この例では 5 つの小惑星、つまり小惑星群を表示します。小惑星群はページの中央に出現し、画面前方に向かって飛んで来て、画面の端に消えていきます (図 4 を参照)。

図 4. 迫りくる小惑星群
迫りくる小惑星群

このエフェクトでは、アニメーションをネストすると共に、互いに作用させる必要があります。さまざまな変換によるエフェクトを重ねていくには、additive="sum" 属性を使用します。最初にネストされた変換は、各小惑星をその軸を中心に回転させるので、小惑星は回転しながら画面前方に向かってくるように見えます。2 番目にネストされた変換は、各小惑星が大きくなるように拡大します (小惑星が接近する様子を表現します)。この 2 つの変換の両方を小惑星の軌道に対して適用するために、use 要素に含めます。グループ全体に適用される外側の変換は、小惑星を画面の端へ向かって移動させ、最終的には画面の外にまで移動させます。

リスト 6 にはアニメーションの 1 つのグループしか記載されていませんが、他のグループも同様です。ただし、画面外の移動先は異なり、さらにそれぞれの小惑星の表示が開始される時刻と表示期間を調整することで、岩がばらばらに飛んでいくようにしています。リスト 6 では、簡潔にするために直線データのほとんどが省略されています。

リスト 6. 小惑星!(変更内容のみ)
<defs>
    [...]
    <path id="rock1" d="M-8 -21 L-9 -21 L-15 -21 [...] />
    <path id="rock2" d="M19 -15 L18 -17 L14 -20 L12 [...] />
    <path id="rock3" d="M-17 -20 L-18 -20 L-19 -20 [...] />
    <path id="rock4" d="M11 -14 L11 -15 L10 -15 [...] />
    <path id="rock5" d="M14 -30 L13 -30 L12 -29 [...] />
</defs>
[...]
<g>
    <use xlink:href="#rock1">
        <animateTransform additive="sum" attributeName="transform"
            type="rotate" from="0" to="360" dur="6s"
            repeatCount="indefinite"/>
        <animateTransform additive="sum" attributeName="transform"
            type="scale" from="0.1" to="6.0" dur="6s"
            repeatCount="indefinite"/>
    </use>
    <animateTransform additive="sum" attributeName="transform"
        type="translate" from="600,400" to="1400,-200" dur="6s"
        repeatCount="indefinite"/>
</g>
[...]

この例をブラウザーで実行するには、サンプル・コード (「ダウンロード」の 06_asteroids.svg) をダウンロードしてください。SVG ビューアーがインストールされている場合は、ここをクリックするとアニメーションを表示することができます。


制約事項

「単純なものは宣言型にすること。複雑なものは手続き型にすること」 ― Adam Bosworth

SVG での宣言型スクリプトには限界があります。衝突を検出し、キーボードによる実際のナビゲーションをするためには、手続き型の JavaScript を追加しなければなりません。SVG 1.2 に制約機能を追加するという話も出ましたが、結局は採用されなかったため、制約は手続き型でコーディングしなければなりません。新しいオブジェクトを追加する場合にも、スクリプトが必要です。HTML と同様に、SVG は上級ユーザー向けのメソッドを DOM インターフェースに追加しています。もちろん、通常の XML DOM メソッドも使用することができます。私は、SVG は大きな転換点に近づいていると思います。この転換点に至った暁には、SVG は急速に普及するようになるはずです。この記事を執筆している時点で、最新のFirefox ベータ版では宣言型アニメーションをサポートしていませんが、Mozilla チームはサポートに向けて取り組んでいるところです。SVG がブラウザーに組み込まれるようになれば、その効果は莫大なものになるでしょう。SVG を生成または表示するための新しいツールは続々と登場しています。SVG にはロケットの赤い光よりも明るい未来が待っています。


ダウンロード

内容ファイル名サイズ
Example SVG codex-matters42-examples.zip14 KB
Example HTML filesx-matters42-html-examplefiles.zip2 KB

参考文献

学ぶために

製品や技術を入手するために

  • Adobe SVG Viewer: この記事の例をテストするために使用したビューアーをダウンロードしてください。
  • Batik: Apache-XML プロジェクトによる Java™ 技術ベースの SVG ツールキットを試してみてください。
  • Compound XML Document Editor: 名前空間が混在する XML 文書に対応するこの標準準拠のモデル駆動型エディターには、SVG と SMIL のサポートが組み込まれています。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, Web development
ArticleID=644697
ArticleTitle=XML の論考: SVG、そしてスクリプトを使わずに作成するスクリプト
publish-date=03092011