FC2ブログ

web用SVGことはじめ 第3回

どうも。ちょっとSVGの話題がノッてきた(一人で)のでいくつか細かいことをやってみます。

'transform'属性のskewX()とskewY()をうまく使う

うまく、というと語弊があるかもしれませんが...前回書いた通り、rotate()は回転中心を変更できましたが、 skewX()とskewY()は中心が原点(その時の原点、というのが正しいですが)になってしまい、原点以外にある要素は、位置によって変形以外に移動してしまいます。しかもその移動量は要素の位置によって違うのです!

そこで、どうするか?具体的には、たとえば長方形をsvg要素の中心においてあるのを、'transform'属性で、そのsvg要素の中心を中心に(^^;)skew変形をするにはどうするか?とくにこの場合は長方形が一つですが、複数のオブジェクトに応用するには、「原点をsvgの中心にする」という安直な解決では対応しがたいです。(じつはこれも適切に対応すれば一つの正解なんですけどね(^^;))

こんかいは、'transform'属性の「行く使いの変形を順次行うことができる」という効用を使って、「一旦要素を動かして原点にもっていき、skew変形をして後、またもとの位置に戻す」という方法で対処してみましょう。

上の場合で説明しましょう。なお当然ですがソース参照です。

<rect>要素の'transform'属性だけ見ると、まずはtranslate()で平行移動をしています('transform'属性のいちばん右が初めに行われる変形)。これは、今回は長方形の真ん中を中心にskew変形するので、"translate(-120 -120)"で真ん中が原点にくるようにしています。さらにそこに"skewX(-30)"をさせて目的の変形を施しました。最後に"translate(120 120)"で元の位置に戻せば完成です。

要点は、skew変形の中心をその時の原点に合わせて、変形して、元の場所に戻す、ということなので、たとえば長方形の左上を中心にして変形したりすることも簡単にできます。また、同じ発想で、X軸やY軸以外の方向に向けてskewすることもできます。この場合はskew変形する方向がX軸になるように一旦回転させてからskew変形を施して元の向きに戻せばいいでしょう。

SMILアニメーションを使ってみる

SMILアニメーションというのは、SVGと同じXMLで定義された、マークアップ言語であるSMILを使ってSVG画像をアニメーションさせることです。ちょうどHTMLにSVGを埋め込むような関係でSVGの中にSMILの要素を入れてアニメーションをさせる感じです。

少し違うのは、HTMLのなかにSVGを埋め込む場合は<svg>要素を使いましたが、SVGをSMILアニメーションするには<smil>要素は使いません。

先に注意しておくと、SVGをアニメーションさせる方法はSMIL以外にもいくつかあります。Javascriptで直接SVGを書き換えたり、実際には私は見たことがありませんがCSS3のアニメーションを応用すれば似たことが出来るようです。どれがいいとは一概には言えませんが、SMILアニメーションはほとんどのメジャーブラウザ(Safari,Google Chrome,Firefox,Opera等)が対応している反面、InternetExplorer(Trident系)は対応していません。

追記:

SVGもSMILもHTML5とCSS3に圧され気味なのか、XMLがレガシー扱いされてるのかわかりませんが、SMILを含むSVGの動作にはかなりブラウザ依存な差があるようです。詳しくは続きの終わりに述べますが、今回の例はほとんどがSafariでは動作しません。現在確認をしているのはGoogle Chromeです。

さて、実際の例を見ましょう。

赤と緑の円がバウンドしているように見えるでしょうか?赤い円が見えるようにfillを透過してあります。

赤い円のバウンド

まずは先に書かれている(そのため下に描かれる)赤い円のアニメーションの指定を見ていきます。

アニメーションは、動かしたい要素の子要素として<animate>要素を与えることで実現しています。

<animate>要素は、その親要素のアニメーション(変化)させたい属性と、その属性の時間による変化をさまざまな方法で記述することができます。すべての指定は属性として行われるので、各属性ごとに役割などを見ていきましょう。

  • 'attributeName'属性

    アニメーションさせる属性の名前を指定します。特に<animate>要素でアニメーションできるのは数値を指定する属性に限られ、"true","false"などの非数値の値をとる属性は<set>要素でアニメーションします。

  • 'attributeType'属性

    'attributeName'属性で指定した属性がCSSのプロパティか、SVG(正確にはXML)の属性かを指定します。今回の'cy','rx','ry'属性はいずれもXMLの属性ですが、CSSプロパティをアニメーションするときは"CSS"を指定します。

  • 'from'属性

    今回はどこにも使用していませんが、属性のアニメーションが始まる時点(特に指定がなければ表示されたとき、あるいはそれから'begin'属性で指定された時間がたった時)での値を指定します。属性がある値から別の値へ単に移動するときに用います。後述の'values'が指定されると無視されます。

  • 'to'属性

    'from'属性と対になって、アニメーションが終了するとき('end'属性で指定された時間か、'begin'属性の時間から'dur'属性の時間だけたったとき)の属性の値を指定します。'from'属性同様単純なアニメーションに用いられます。後述の'values'が指定されると無視されます。'from'属性と'to'属性'を指定して行うアニメーションを"from-toアニメーション"といい、<animate>要素には'to'属性のみを指定して、アニメーションする要素に属性を指定しておくアニメーションを"toアニメーション"と言います。

  • 'by'属性

    'to'属性の代わりに指定して、属性がアニメーション終了までに変化する量を指定します。標語的にいえば、「'to'-'from'='by'のとき同じアニメーションを意味する」と言えるでしょう。後述の'values'が指定されると無視されます。'from'属性と'by'属性'を指定して行うアニメーションを"from-byアニメーション"といい、<animate>要素には'by'属性のみを指定して、アニメーションする要素に属性を指定しておくアニメーションを"byアニメーション"と言います。

  • 'values'属性

    アニメーションの開始から終了までの'keytimes'属性で指定した各時間での属性の値をセミコロン(";")区切りのリストで指定します。属性が複数の値をとる場合でも属性に応じた表記をセミコロンで区切って指定します。アニメーションする間複雑な動きをする場合は'from'などは使わずこれを用います。'values'属性のみを指定するアニメーションを"valuesアニメーション"と言います。

  • 'begin'属性

    アニメーションの開始時刻を指定します。ページが表示されてからの実時間("4s"="4秒"、"2:30"="2分30秒"など)で指定され、アニメーション全体の開始をします。繰り返しを含むアニメーションでも、最初の一回の開始時刻を指定することになります。

  • 'end'属性

    アニメーションの終了時刻を指定します。あくまでも'begin'属性の"終了"版なので、たとえば「end="3s"」と指定すると、ページが表示されてから3秒後にはアニメーションが終了します。始まっていなくても。単純なアニメーション(from-toアニメーションなど)を、ページが表示されてから3秒後に開始して6秒後に終了したい場合は「begin="3s" end="6s"」とするか、「begin="3s" dur="3s"」としてください。また、後述する、アニメーションの繰り返しをするときは基本的に'end'属性を指定しないか、「end="indefinite"」(つまり「定義しない」を定義する)ようにしないと、繰り返しが途中で止まります。

  • 'dur'属性

    アニメーションの継続時間を指定します。繰り返さない場合はアニメーションする総時間を、繰返しをする場合は一回の繰り返し時間を指定します。'begin'と'end'属性が、繰返しも含めたアニメーション全体の時間を決定するのに対して若干の違いがあります。

  • 'keyTimes'属性

    'from'に対する'begin'、'to'に対する'end'のように、'values'で与えられる複数の値がいつの時点での値かを指定します。但し実際の時間ではなく、'dur'属性の時間の初めを0、終わりを1とするときのどの時点かという比で指定します。'values'属性と同様にセミコロンで区切った値のリストで指定します。'values'属性とリストの要素の個数が異なるとエラーになります。

  • 'repeatCount'属性

    繰り返しの回数を指定します。普通に数字を指定すると、'end'属性で指定された終了時刻まではその回数だけ繰り返そうとします('end'属性で指定した終了時刻になれば終了)。また、無限に繰り返したい場合は"indefinite"("定義しない"の意)を設定すると'endまで'繰り返し続けます。

...複雑ですよね。

ちなみに上では簡単な使い方のみ抽出して説明しているため、たとえば'begin'属性や'end'属性にリスト指定ができることや、値として"click"のようなインタラクションに応用できそうな開始・終了時刻(クリックされたときに...ということ)が使えることも特に触れていません。が、アニメーションするだけなら上だけで十分です。詳しく知りたい方は頑張ってSVGの仕様書またはその日本語訳を読んでください。ちなみにSMILの仕様書とかにも手を出すことになるのでわかったらむしろ教えてください。(ぇ

さてさて、今の赤い円の例は実はずるをしていることに気づかれたでしょうか?円や長方形の場合は今の例のように<ellipse>を使って伸縮を表現できますが、ふつうはそういうことはできないので、他のものでも使える方法も示しておきましょう。それが緑の円です。

少し動きも変わって、飛び上がった時に高く上がるほどなめらかに減速しているのがわかるでしょうか?特に赤い円と比較するとわかりやすいと思います。赤い円は比較してみると上の端にぶつかって跳ね返ったようにも見えますが、戻りの円はふんわりと落ちてきている感じに見えないでしょうか?<animate>要素と、次の<animateTransform>要素は類似の属性が多いのでそのあたりに重点を置いて解説します。

  • 'attributeName','attributeType','from','to','by','values','begin','end','dur','keyTimes','repeatCount'属性

    <animate>要素とまったく同様です。'attributeName'には"transform"が指定されるはずです。

  • 'type'属性

    'transform'属性のどのような変形要素(translate,rotate,scale,skewX,skewY)をアニメーションするかを指定します。

  • 'additive'属性

    指定されたアニメーションを、既存の'transform'属性の値と置き換えるのか("replace")、そこに新たな変形として加えるのか("sum")を指定します。"既存の'transform属性'の値"とは、親要素の属性として直接指定されている属性値に、この属性を含む<animateTransform>要素以前(上)に書かれている<animate>要素や<animateTransform>要素による変形を加えた(あるいは置き換えられているかもしれないが)変形のことです。今回の例では<g>要素の子として<animateTransform>要素が指定されていますが、一つ目の<animateTransform>要素は置き換え("replace")を選んでいますが、今回は<g>要素には何の変形も施されていないうえ、置き換えはデフォルト値なので特に指定しなくてもかまいません。さらに二つ目の<animateTransform>要素は"sum"を選択しています。これは、一つ目の<animateTransform>要素で<g>要素全体が移動するアニメーションを指定し、二つ目の<animateTransform>要素でバウンドするときの円の変形を表現するためで、置き換えてしまうとただの円が伸縮するアニメーションになってしまうためです。

  • 'calcMode'属性

    アニメーションの補間方式を選べます。なおこの属性は<animate>要素でも利用できます。デフォルトでは"linear"が指定され、赤い円のようなことになります。しかしここで"spline"を指定して、次の'keySplines'属性で正しい指定をすればなめらかな運動をさせることができます。また、むしろとびとびの値をとらせる"discrete"と、パスアニメーションを設定する<animateMotion>要素向けにの"paced"も指定できますが、<animate>や<animateTransform>で指定するのは珍しいでしょう。

  • 'keySplines'属性

    'calcMode'属性で"spline"が指定されたときのみ有効。この属性も<animate>要素でも利用できます。「空白区切りの4つの数値のリスト」をセミコロン区切りのリストで指定します。'values'属性や'keyTimes'属性のリストより一つ少ないリストでないとエラーになります。リストの要素である「空白区切りの4つの数値のリスト」は、アニメーションされる二つの値の間の状態での属性値を計算する補間のためのベジェ曲線の2つの制御点を指定します。制御点は初めの属性値と時刻を(0,0)、後の属性値と時刻を(1,1)とする相対値で指定します。

どうでしょうか?簡単なアニメーションなら作れそうな気がしてきませんか?

もうずいぶんと長くなってしまったので一旦ここで終わりにしましょう。

え~と、やりたくない、というか考えたくないことですが実用上重要な、ブラウザの対応状況です。

BrowserHTML + inline SVGHTML + SVG ObjectSVG standalone
InternetExporer9 ××△?
Safari5.1.7 ×
Google Chrome21.0
Mozilla Firefox15.0.1
Opera12.02

いずれも、表中の○×は、表示されるかではなく、正しいアニメーションが再生されるか、までで判定しているので、正しく再生されないものは×にしています。

「HTML + inline SVG」というのは、HTMLにインラインでSVGを埋め込んだ場合です。今回の本文でも使用しているので、本文を再生しながらご覧になりたい場合はこれが○のブラウザを使用してください。SVGやSMILはHTML中に埋め込まれているのでこれの解釈と視覚化は一般的にはレンダリングエンジンの仕事だと思います(実は詳しくない)ので、これらと共通のレンダリングエンジンを使用しているブラウザならば閲覧できる可能性は高いと思います。(最近知りましたがGoogleChromeはwebkit、Safariはwebkit2を使ってるんですね)

「HTML + SVG Object」は、<object>要素を使って、独立したSVGファイルを読み込んだ場合です。独立したSVGファイルというのは、下で説明する「SVG standarlone」において読み込ませたファイルをそのまま指定しています。

「SVG standalone」は、独立したSVGファイルを直接ブラウザに開かせた場合です。InternetExplorer9が「△?」になっているのは、ローカルファイルシステムからSVGファイルを開くと正しく再生されますが、ローカルのwebサーバーに接続してみる場合は再生されませんでした。これ以外で、ローカルファイルシステムへのアクセスとローカルwebサーバーへのアクセスで結果の異なるブラウザはありませんでした。

最後に、参考までに<object>要素での埋め込みとSVGファイルを作成した時の私の例を示しておきます。実際に利用される場合に参考にしていただいたり、ここがおかしい、等のご指摘があればいただきたいと思います。

SVGファイルを作成するのにあたってソースに追加したこと

以下のコードをファイルの先頭に追加したうえで、さらに<svg>要素の属性として「xmlns="http://www.w3.org/2000/svg"」を追加しました。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<object>要素による埋め込み方法

単に以下のコードでhtmlファイル中に埋め込みました。

<object data="./smil.svg" width="240px" height="240px"></object>

もちろん埋め込んだHTMLファイルと埋め込まれたSVGファイルは同じフォルダにあります。

スポンサーサイト



コメント

非公開コメント

プロフィール

f(t)=k

Author:f(t)=k
ベクトル画像をもっと世に広めたい一般人その1

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR