2012年8月17日金曜日

svgが参照しているスタイルシートをスクリプトで変更する

htmlでは通常外部cssを参照する場合にlink要素を使います.従ってスクリプトからはこのlink要素を操作することでスタイルシートの参照先を変えることができます.そこでsvgでも同様のことができて当たり前と考えるのが筋です.しかしsvg文書となるとlink要素に相当するものは有りません.html5で導入されたインラインsvgであればhtmlの機構を使ってcssを参照できるので問題ないのですが…

さて,どうすれば良いのでしょうか?

これを解決する方法をとりあえず2つ見つけましたので,まとめておきます.

1.ProcessingInstructionオブジェクトを用いる方法

<?xml-stylesheet href="cssa.css" type="text/css"?>処理命令に相当するProcessingInstructionオブジェクトを取得してファイルの参照先を書き換える方法です.
documentのstyleSheetsプロパティから現在参照しているスタイルシートを取得し,そこからそのスタイルシートを定義しているProcessingInstructionオブジェクトを取得します.このオブジェクトのnodeValueには「href」以下の設定情報が格納されているので,これを書き換えてしまいます.

早速試してみましょう.下の例はスクリプトを使ってもともと赤色だった矩形をスタイルシートの参照先を変えることで青色としています.



<?xml version="1.0" standalone="no"?>
<?xml-stylesheet href="cssa.css" type="text/css"?>
<svg width="200px" height="200px" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
 <rect x="20" y="20" width="160" height="160"/>
 <script>
window.onload = function(){
 //既存のxml-stylesheet処理命令にアクセスするには
 //[1]document.styleSheets.item(0)でStyleSheetオブジェクトを取得し,
 //[2]ownerNodeプロパティからProcessingInstructionオブジェクトを参照する.
 document.styleSheets.item(0).ownerNode.nodeValue = 'href="cssb.css" type="text/css"';
};
 </script>
</svg>

この方法は発想としては自然なのですが,operaでは動作しませんでした.またブラウザ毎に実装が異なるようで,あまり使い勝手はよく有りません.

2.@import規則を用いる方法

ではもっと素朴に実現する方法は無いのかと考えてみますと,cssにはもともと@import規則を使って外部cssファイルを参照する機能が定義されています.という事は,style要素を使って@import規則を追加すれば何とかなりそうです.style要素であれば,これまでどおりの使い勝手となるはずです.ではやってみましょう.



<?xml version="1.0" standalone="no"?>
<?xml-stylesheet href="cssa.css" type="text/css"?>
<svg width="200px" height="200px" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
 <rect x="20" y="20" width="160" height="160"/>
 <script>
window.onload = function(){
 //style要素を生成し,文書に挿入する.
 var style = document.createElementNS("http://www.w3.org/2000/svg", "style");
 style.textContent = "@import url(cssb.css)";
 document.documentElement.appendChild(style);
};
 </script>
</svg>

おそらく,正しく動作したことと思います.この方法なら左記ほどと異なり,firefox,chrome,operaで動作します.従って,通常はこちらの方法を用いればよいでしょう.

なお,この方法はあくまでもcssの参照を追加しただけですので,元から有るcssの内容を上書きしていることになります.よって,xml-stylesheet処理命令で参照するcssと動的に変化させたいcssとの間に矛盾が生じないようにスタイルシートを構成する必要があるでしょう.

0 件のコメント:

コメントを投稿