データURIスキームにSVGを指定して動的に書き換えてみた

SI部のモグです。
業務でデータURIスキームを使った時に思い浮かび、データURIスキームにSVGファイルを指定して動的に書き換えてみました。
データURIスキームとは、HTMLのimgタグなどに直接データをbase64形式で記述することで、外部のファイルにアクセスせず表示させる事ができます。
コードの容量が若干増えますが、リクエストやファイル数を減らすメリットがあり、htmlファイル1つで完結させたいなどの特定状況下で需要があります。
SVGファイルはxmlで記述されたベクター画像です。
アイコン等に使われる事が多いです。
データURIスキームとSVGファイルは、いずれも近年のブラウザではほとんど対応されているため、これを組み合わせてJavaScriptで動的に書き換える事をやってみました。
以下ソースです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script>
function changeIcon(){
//SVGのXML
var svg =
'<?xml version="1.0" encoding="UTF-8"?>'
+ '<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">'
+ ' <rect x="5" y="5" rx="10" ry="10" width="40" height="40" fill="green" />'
+ ' <g fill="white" font-size="25">'
+ ' <text x="13" y="35">い</text>'
+ ' </g>'
+ ' <circle cx="40" cy="10" r="8" fill="red"/>'
+ ' <g fill="white" font-size="5">'
+ ' <text x="39" y="13">2</text>'
+ ' </g>'
+ '</svg>';
//SVGをbase64に変換する
var b64 = window.btoa( unescape(encodeURIComponent( svg )) );
//idがimg1のタグのエレメント
var img1 = document.getElementById("img1");
//img1のsrcを書き換える
img1.src = "data:image/svg+xml;charset=utf-8;base64,"+b64;
}
</script>
</head>
<body>
<!-- クリックするとchangeIcon関数を呼ばれ画像が挿し変わります。srcには最初に表示される画像がbase64で書いてあります。 -->
<img id="img1" onClick="changeIcon()" src="data:image/svg+xml;charset=utf-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNTAiIGhlaWdodD0iNTAiPg0KPCEtLeODmeODvOOCueOBrue3kemDqOWIhi0tPg0KICAgIDxyZWN0IHg9IjUiIHk9IjUiIHJ4PSIxMCIgcnk9IjEwIiB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIGZpbGw9ImdyZWVuIiAvPg0KPCEtLeS4reWkruOBriLjgYIiLS0+DQogICAgPGcgZmlsbD0id2hpdGUiIGZvbnQtc2l6ZT0iMjUiPg0KICAgICAgICA8dGV4dCB4PSIxMyIgeT0iMzUiPuOBgjwvdGV4dD4NCiAgICA8L2c+DQo8IS0t5Y+z5LiK44Gu6LWk5Li4LS0+DQogICAgPGNpcmNsZSBjeD0iNDAiIGN5PSIxMCIgcj0iOCIgIGZpbGw9InJlZCIvPg0KPCEtLei1pOS4uOWGheOBriIxIi0tPg0KICAgIDxnIGZpbGw9IndoaXRlIiBmb250LXNpemU9IjUiPg0KICAgICAgICA8dGV4dCB4PSIzOSIgeT0iMTMiPjE8L3RleHQ+DQogICAgPC9nPg0KPC9zdmc+DQo=">
</body>
</html>
まずこのhtmlの前にSVGファイルを準備します。
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
<!--ベースの緑部分-->
<rect x="5" y="5" rx="10" ry="10" width="40" height="40" fill="green" />
<!--中央の"あ"-->
<g fill="white" font-size="25">
<text x="13" y="35">あ</text>
</g>
<!--右上の赤丸-->
<circle cx="40" cy="10" r="8" fill="red"/>
<!--赤丸内の"1"-->
<g fill="white" font-size="5">
<text x="39" y="13">1</text>
</g>
</svg>
次にこのSVGファイルをbase64に変換します。
“PD94bWwgdm~”のような長い文字列になります。
この文字列を上記HTMLのimgタグに記述します。
<img src="data:image/svg+xml;base64,[ココに書く]">
ちなみにSVGのMIMEタイプは「image/svg+xml」です。
これで上記のSVG画像が初期表示されます。(「あ」が出ます)
このimgタグにonClick=”changeIcon()”と指定してあるので、
「あ」のアイコンをクリックするとchangeIcon()が実行されます。
このchangeIcon関数では、
- SVGファイル用のxmlを新しく生成して、
- それをbase64に変換して、
- imgタグのsrcを書き換える
という処理をしています。
クリックすると画像が「い」になり数字が2になります。
これを利用してアニメーションGIFやswfバナーのようなものをインラインで実装できたり、動的なアイコンがベクター画像で作れたりできます。
と、強引にメリットを絞り出してみますが、こんなまどろっこしい事やるくらいならjavascriptで全部実装した方がシンプルですよね・・
ただ、部分的には使うケースが出てきそうそうな機能なので、忘れないようにここに書き記しておきます。
