HTML中のSVG要素を出力(dataスキーム使用)

2011/04/08 3:33 PM

 

Protovisなどを使用してHTML画面上に生成したSVG画像を、ローカルに保存したい場合がある。

ローカルのファイルとして保存する実装はブラウザによってさまざまだが、別ウィンドウに出力したものを名前を付けて保存する方法なら、たいていのブラウザでできる。
ここでは、dataスキームを使用する方法を採用、SVGをXML文書として開かせる方法を以下に載せる。

ソース:

/**
* ドキュメント内のSVGを別ウィンドウで出力する。
* 引数svgIndexには、ドキュメント内のSVG要素のインデックスを指定すること。
* (指定しない場合は0。最初のSVG要素とみなされる)
*/
function exportSVG(svgIndex){
    
    if (!svgIndex) {
        svgIndex = 0;
    }

    // SVG要素を取得。
    var svgNode = document.getElementsByTagName(“svg”)[svgIndex];

    // 生成されるXMLにSVGのネームスペースを指定。
    svgNode.setAttribute(“xmlns”, “http://www.w3.org/2000/svg”);    

    // XMLドキュメント宣言
    var svgText = “\n”;

    // 出力するXML(テキスト)SVG要素を追加する。
    svgText += svgNode.parentNode.innerHTML;
    //alert(svgText);
    
    // SVG-XMLを文字列化したものをdataスキームで生成
    // エスケープ(UTF-16文字列はエスケープ解除)
    var data = “data:image/svg+xml;charset=UTF-8,” + UnescapeUTF16Only(escape(svgText));

    // 別ウィンドウ(_blank)に出力
    var svgWindow = window.open(data, “SVG”, “_blank”);
}

function UnescapeUTF16Only(s) {
    return s.replace(/%u\w\w\w\w/g, UnescapeUTF16);
}

function UnescapeUTF16(s) {
    return unescape(s);
}

解説:
ドキュメント内あるSVGは一つとは限らないので、svgタグのインデックスを指定できるようにしている。
また、svg要素に”http://www.w3.org/2000/svg”のXML名前空間(xmlns)を、追加しないと、正しくレンダリングされない。

dataスキームとしてSVGを整形し、別ウィンドウのURLとして指定している。
dataスキームとは、URLの拡張であり、画像、音声など、これまで参照として指定していたデータを、インラインで記述できるリソース指定方法。
これまでの方法では、まず、HTMLをブラウザが解釈、参照先のデータ一つ一つをブラウザが取得しに行っていたため、リクエストのボトルネックがあった。dataスキームを使用すると、最初のアクセスで画像などのリソースが一度に取得できるため、リクエスト数を減らすことができる。
(高速化の基本は、リクエストを最小限にすること)
Webアプリで小さな画像がたくさんある場合など、サーバでのbase64のエンコード負荷とブラウザのリクエスト・ボトルネックのバランスを見て実装すべし。

補足:
Protovisでグラフを描くと、

script type=”text/javascript+protovis”

のブロックの一つ前にspan要素が作られ、その中にsvg要素が生成されるようだ。
ただ、そのsvg要素にはid、name属性などは付いていないので、直接指定はできない。
そのため、このサンプルでは、document.getElementsByTagNameでsvgタグを指定して取得した配列を使用している。

エスケープの部分などを、北島 敦記様のサイトを参考にさせていただいた。
http://www.h6.dion.ne.jp/~lib-k/SVGByJavaScript/SVGByJavaScriptData.html



コメントはまだありません

まだコメントはありません。

RSS feed for comments on this post. TrackBack URI

コメントを書く

WordPress Themes