2012年9月22日土曜日

svgのテンプレートに対するスタイル指定を単純化する方法

引き続きuse要素の動作について考えてみます.前回示した通り,テンプレートとなる図形に対してスタイルを指定する際,use要素の実装の違いからfirefoxとchrome/operaで動作が異なります.この違いはスタイルシートの記述を2系統用意することで解決するとしていましたが,実はもっと良い方法がありました.

まずはおさらいです.use要素の実装には(1)参照先の要素のクローンを作るものと(2)プロキシオブジェクトを生成するものの2つがあるとしました.

ここでfirefoxは(1)の実装法を,chrome/operaでは(2)の実装法を採用しているため,スタイルの指定に違いが表れるのでした.

そのため,firefoxにおいてはテンプレートとなる要素にスタイルを指定するのではなく,use要素の下にテンプレートがあるものとしてセレクタを記述する必要がある訳です.例を示します.何れもテンプレートとなるcircle要素にスタイルシートから塗り潰しの色を指定しています.

A)下記の例はfirefoxでは正しく動作しません.

<svg id="use_type">
 <style>
  svg#use_type defs>#template1{
   fill:red;
  }
 </style>
 <defs>
  <circle id="template1" cx="100" cy="100" r="80"/>
 </defs>
 <use xlink:href="#template1"/>
</svg>

B)こちらの例はuse要素の下に要素が存在していると仮定してセレクタを設定したものです.firefoxでは動作しますが,今度はchrome/operaで動作しません.

<svg id="use_type2">
 <style>
  svg#use_type2 use>#template2{
   fill:red;
  }
 </style>
 <defs>
  <circle id="template2" cx="100" cy="100" r="80"/>
 </defs>
 <use xlink:href="#template2"/>
</svg>

C)よってクロスブラウザで動作させるにはA)とB)のスタイルシート指定を併記する必要があるのですが,これではいささかコードが冗長であり,記述ミスの恐れもあります.
そこで今回編み出した方法がテンプレートを定義しているdefs要素と,そのテンプレートを使っているuse要素に同じクラスを設定する方法です.
それでは実際に試してみましょう.


<svg id="use_type3">
 <style>
  svg#use_type3 .common>#template3{
   fill:red;
  }
 </style>
 <defs class="common">
  <circle id="template3" cx="100" cy="100" r="80"/>
 </defs>
 <use class="common" xlink:href="#template3"/>
</svg>

非常にすっきりと書けました.画像の描画に直接関係しないdefs要素にクラスを指定するのは意外に思われますが,確かにセレクタとしては正しい動作になりますね.


個人的な感想ですが,svgの要素をいろいろ試してみる内にsvgの真価はアニメーションでも,フィルターでも無くuse要素なんじゃないかとも思い始めています.htmlでは要素のコピーをすることが出来ませんが,svgでは自由自在です.普段は使わない要素かも知れませんが,工夫次第で様々な用途に用いることができるため,ぜひ試してみることをお勧めします.

ps.safariとかieでも動くといいなあ.(未確認なんです…)

0 件のコメント:

コメントを投稿