SVG.toDataURL

https://github.com/sampumon/SVG.toDataURL
を使おうとしたら日本語ダメです状態だったお話。

<!DOCTYPE html>
<html>
    <head>
        <title>さんぷる</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script type="text/javascript" src="js/base64.js"></script>
        <script type="text/javascript" src="js/svg_todataurl.js"></script>
        <script>
            window.onload = function() {
                document.getElementById("svg").toDataURL("image/png", {
                   callback : function(data) {
                       document.getElementById("render").setAttribute("src", data);
                   } 
                });                
            }
        </script>
    </head>
    <body>
        <iframe id="render" width="600" height="600"></iframe>
        <svg id="svg" viewBox="-110 -160 220 220" width="400" height="400">
            <g fill="none" stroke="black">
                <path d="M 0,0 m-90,-90 c30,60 60,90 90,90 c30,0 60,-30 90,-90" stroke-width="2"/>
                <line x1="-100" y1="0" x2="100" y2="0"/>
                <line x1="0" y1="-150" x2="0" y2="50"/>
            </g>
            <g stroke="blue" stroke-width="4">
                <line x1="0" y1="0" x2="30" y2="0"/>
                <line x1="60" y1="-30" x2="90" y2="-90"/>
            </g>
        </svg>
    </body>
</html>

日本語がないと
f:id:ebifly10:20141007222758p:plain
こんな感じで表示される。

SVG部分をこんな感じに変えると

<svg id="svg" viewBox="-110 -160 220 220" width="400" height="400">
    <g fill="none" stroke="black">
        <path d="M 0,0 m-90,-90 c30,60 60,90 90,90 c30,0 60,-30 90,-90" stroke-width="2"/>
        <line x1="-100" y1="0" x2="100" y2="0"/>
        <line x1="0" y1="-150" x2="0" y2="50"/>
    </g>
    <g stroke="blue" stroke-width="4">
        <line x1="0" y1="0" x2="30" y2="0"/>
        <line x1="60" y1="-30" x2="90" y2="-90"/>
    </g>
    <text x="10" y="20">基本形:y=x^2</text>
</svg>

f:id:ebifly10:20141007223103p:plain

Uncaught InvalidCharacterError: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

btoaでLatin1の範囲外の文字はエンコードできねーぞバーローと怒られました。

btoaのドキュメント見るとちゃんと
https://developer.mozilla.org/ja/docs/Web/API/window.btoa

殆どのブラウザでは、window.btoa のパラメータにユニコードの文字列を指定して呼び出すと、例外「範囲外 (Out Of Range)」が返ります。

とあたり前のように記載されていました。
これを解決するにはすぐ下にあるようにunescapeとencodeURLComponentで括ってやればいいそうです。

  • svg_todataurl.js
function base64dataURLencode(s) {
        var b64 = "data:image/svg+xml;base64,";

        // https://developer.mozilla.org/en/DOM/window.btoa
        if (window.btoa) {
                debug("using window.btoa for base64 encoding");
                b64 += btoa(unescape(encodeURIComponent(s)));
        } else {
                debug("using custom base64 encoder");
                b64 += Base64.encode(s);
        }

        return b64;
}

と変えるだけで
f:id:ebifly10:20141007224006p:plain
と表示されるように・・・あれ?

どうやらsvg要素内で明示的にサイズ指定しないとダメなようです。

<text x="10" y="20" font-size="14px">基本形:y=x^2</text>

f:id:ebifly10:20141007224209p:plain
これで無事想定通りの出力が得られました。

実装力なくてもググれれば結構なんとかなっちゃう時代ですね。
いいのやら悪いのやら。

btoa(unescape(encodeURIComponent(s)));でなんでおっけーかはこちらが分かりやすかった。
【JavaScript】window.btoa(‘日本語’) する at softelメモ

SVG部分は以下のサイトからお借りしました。
http://www.h2.dion.ne.jp/~defghi/svgMemo/svgMemo_03.htm