use要素は既存の図形要素を複写する機能をもちます.単一の図形を何度も使いまわすことができるのでsvgを手書きする場合や,図形をテンプレート化する際に非常に重宝する要素です.
ここで「図形を複写する」とは一体どのような仕組みで行われているのでしょうか?色々とsvgを弄ってみて判ったこととして概ね次の2つの実装に分けられるようです.(なおいずれも推測の域は出ません.)
- 元となる図形要素を実際にコピーする.つまりdomオブジェクトのcloneを作る.
→firefox - 元となる図形要素を参照するプロキシオブジェクトを生成する.
→chrome,opera
この実装の違いにより様々な動作の違いが発生します.
- firefoxではuse要素でコピーした要素にスタイルを指定することができてしまう.
通常use要素の子要素としては図形要素は存在しないはずなのに,あたかも参照先の図形がuse要素の配下に存在するかのようにcssが動作してしまいます.
例)use rect{fill:red}
つまり内部的にcloneを生成している事になります.
chrome,operaではuse要素の内部に存在するのは元となる図形への参照情報だけなので,スタイルを指定することができません. - firefoxにおいてuse要素からsmilアニメーションが設定されている要素を参照した場合,そのアニメーションがxlink:href属性によって外側から定義されていた場合,use要素側のアニメーションは動作しない.
これは要素のクローンを作ったためにアニメーション対象から外れたものと考えられます.
chrome,operaではプロキシオブジェクトを経由してアニメーションを描画するので,use要素側でもアニメーションが実行されます. - イベントを発生する主体が異なる.
svg要素で子要素から浮上してきたイベントを確認すると,イベントを発生した主体がfirefoxではSVGUseElementが,chromeとoperaではSVGElementInstanceが得られます.
特にuse要素とanimate要素とは相性が良くないようです.smilだけではどうしても上手く行かない場合はjavascriptを使ってdomを操作することを検討しましょう.domによるアニメーションは経験上素直に動作することが多いです.
サンプル
<script type="text/javascript">
window.addEventListener("load", function(){
var svg = document.querySelector("svg:last-child");
var result = document.querySelector("#result");
svg.addEventListener("click", function(e){
result.innerHTML = e.target;
}, false);
}, false);
</script>
<p>スタイルの適用</p>
<svg id="svg1">
<defs>
<rect id="rect1" width="100%" height="100%"/>
</defs>
<use xlink:href="#rect1"/>
</svg>
<p>アニメーション設定済み要素の参照</p>
<svg viewBox="-100,-100,200,200">
<defs>
<rect id="rect2" x="-100" y="-100" width="100%" height="100%"/>
<animateTransform xlink:href="#rect2" attributeName="transform" type="rotate" from="0,0,0" to="360,0,0"
begin="0s" dur="6s" repeatCount="indefinite"/>
</defs>
<use xlink:href="#rect2"/>
</svg>
<p>イベント発生の主体:<span id="result"></span></p>
<svg id="svg3">
<defs>
<g id="click">
<rect width="100%" height="100%"/>
<text y="50" fill="white" font-size="25" font-family="sans-serif">click me!</text>
</g>
</defs>
<use xlink:href="#click"/>
</svg>
0 件のコメント:
コメントを投稿