となると,更なる疑問として「svgをサポートする環境でのみ適用されるスタイル」は作れるのか?問題が生まれてきます.また,styleと似た立ち位置に居るscript要素についても同様のことを考えることができます.
なお結論から言うと,svgをサポートする環境で「のみ」動作するスタイル・スクリプトをdomの構造だけで指定することは不可能か不完全です.本記事ではこれらについての考察をまとめたもので,完璧な解決策を与えるものではありません.
※誰かsafari6とか,試してみてくれんかなー・・・
問題提起・svgのサポート状態でhtmlの処理を切り替えたい.
現状svgをサポートしないwebブラウザの存在がsvg普及の足枷となっているのは否定できないことだと思います.従ってsvgのサポート状況によって処理の振り分けを考えるのは自然なことです.
ここでの処理とはスタイルの適用とスクリプト処理を指すこととします.すると,今回検討すべき問題は次の4つに集約されることとなります.
(1)svgをサポートする環境 でのみ動作するスタイル | (2)svgをサポートしない環境 でのみ動作するスタイル |
(3)svgをサポートする環境 でのみ動作するスクリプト | (4)svgをサポートしない環境 でのみ動作するスクリプト |
スタイル指定における考察
スタイルにおいては前回見た通りmetadata要素とlink要素とを組み合わせることでsvgをサポートしない環境でのみ動作するスタイル(つまり2番)を定義できることが判っています.
ですがこれはあくまでスタイルを追加するケースであって,(1)の「svgをサポートする環境でのみ動作するスタイル」を指定したことにはなりません.ではどうすれば良いのでしょうか?
この問題についていろいろ考えたのですが,筆者は不可能と結論付けます.
根拠としてはインラインsvgを含むhtml文書において,スタイルを指定する方法はlink要素を用いる方法とstyle要素を用いる方法の二つがありますが,これらは何れもsvgをサポートしない環境でも自動的に有効となってしまうからです.
(xml−stylesheet命令を使う方法はスタンドアロンのsvgでのみ有効な方法です)
従って何らかの補助的な手段(例えばjavascript) を利用する必要が出てきます.
スクリプトにおける考察
同様のことをscript要素について考えてみましょう.script要素において外部スクリプトファイルを参照する方法はhtmlとsvgとで異なります.- htmlの場合・・・src属性から参照する
- svgの場合・・・xlink:href属性から参照する
例えば次のようなコードを考えてみましょう.
<html> <body> <svg> <script xlink:href="a.js"></script>
<script src="b.js"></script>
</svg> </body> </html>
これをsvgのサポート状況毎に考えてみると,次のようになるでしょう.
svgをサポートする環境ではsvg要素配下のscript要素のうち,xlink:href属性を使って外部コードを参照している要素が正しい事になります.→つまりa.jsが実行されます.
svgをサポートしない環境ではsvg要素の存在が無視されます.従ってsrc属性を使って外部コードを参照している要素が正しいことになります.→つまりb.jsが実行されます.
このように処理の振り分けができました.従ってsvgが有効な環境でのみ有効となるスタイルもこのscript要素の効果を用いればなんとかなりそうです.
サンプルコードの記述
以上のことを踏まえて次のようなサンプルコードを記述して見ました.
●メインとなるhtml文書
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
</head>
<body>
<svg display="none">
<!--svgをサポートする環境で実行したいもの-->
<!--スクリプトレスでスタイルを指定する方法は無いので,スクリプト内部でスタイルを指定する.-->
<script xlink:href="style.js"></script>
<script xlink:href="svg.js"></script>
<!--svgをサポートしない環境で実行したいもの-->
<metadata>
<link rel="stylesheet" href="nonsvg.css" type="text/css"/>
</metadata>
<script src="nonsvg.js"></script>
</svg>
<div id="msg1"></div>
<div id="msg2"></div>
</body>
</html>
○svgが有効な環境で動作させたいもの
●style.js
※スタイルを追加するスクリプト
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = "svg.css";
link.type = "text/css";
document.head.appendChild(link);
●svg.css
div{
color:blue;
}
●svg.js
window.onload = function(){
document.getElementById("msg1").innerHTML = "svgサポート";
};
○svgが無効な環境で動作させたいもの
●nonsvg.css
div{
color:red;
}
●nonsvg.js
window.onload = function(){
document.getElementById("msg2").innerHTML = "svg非サポート";
};
このコードを実行すると次のようになるはずです.
- svgをサポートする環境では青い文字で「svgサポート」と表示される.
- svgをサポートしない環境では赤い文字で「svg非サポート」と表示される.
実際に試してみると・・・
辻褄上はこれで全て問題は解決されるはずなのですが・・・意外な結果が得られました.
- firefox・・・問題なし
- chrome・・・問題なし
- opera・・・問題なし
- safari5・・・正常に動作せず
- ie6,7,8・・・問題なし
- ie9,10・・・問題なし
safariと言えばios系の環境における標準的なブラウザですから,多くの環境で利用されていることが想像できます.従ってこの方法を利用するにはデメリットが余りに大きいこととなります.
※なお,上記の結果から「svgをサポートしない環境でのみ実行されるscript要素」は問題なく動作していることが判ります.
svgの動作を判定するもうひとつの方法
ではこの他にsvgのサポート有無を判定する方法は無いのでしょうか?実はあります.svgdomの定義有無を確認するのです.例を示します.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
</head>
<body>
<div id="msg"></div>
<script type="text/javascript">
var msg = document.getElementById("msg");
if(document.createElementNS && document.createElementNS("http://www.w3.org/2000/svg", "svg").viewBox){
msg.innerHTML = "svgサポート";
}else{
msg.innerHTML = "svg非サポート";
}
</script>
</body>
</html>
- documentオブジェクトがcreateElementNSメソッドを持っているかを確認します.
→レガシーieのふるい落とし - createElementNSメソッドで試しにsvg要素し,その内容がviewBoxプロパティを持っているかを確認します.
→古いandroid環境では空のsvgオブジェクトが生成されます.
まとめ
以上のことから,svgのサポート有無による処理の振り分けを行う場合は次のようにするとよいでしょう.
- スタイルは通常svgをサポートする環境での設定をメインとし,非サポート環境で必要となるスタイルは前回紹介した「svg-metadata-link」 パターンで追加(上書き)指定します.
- スクリプトはsvgdomの実装有無で処理を分岐しましょう.
- script要素の属性を使った処理の振り分けはsvgをサポートしない環境でのみスクリプトを実行したい場合に有効で,その逆はsafariで問題を起こします.
0 件のコメント:
コメントを投稿