データ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で全部実装した方がシンプルですよね・・
ただ、部分的には使うケースが出てきそうそうな機能なので、忘れないようにここに書き記しておきます。