SVGは、ブラウザで表示して使うことを想定しています。今までの勉強で静止画(ロゴなど)は、問題なく扱えるようになったと思います。ここからは一歩踏み込んで、JavaScriptを含むSVGをHTMLに読み込ませる方法を勉強しました。
実現したいこと
JavaScriptを含むSVGをHTMLに読み込ませたいです。
SVGの勉強をしていくうちに、このように考えると思います。HTMLには、以下のように最小限のコードで追加したいです。
<!-- sample.html --> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>SVGの練習</title> </head> <body> ... <!-- SVGの読み込み --> <object data="sample.svg" type="image/svg+xml"></object> ... </body> </html>
現状
現状、SVG+JavaScriptをブラウザで実現するには、HTMLに直書きするか、objectタグで読み込む方法の2択のようです。JavaScriptを含むSVGをobjectタグで読み込む場合、ブラウザの対応状況がまちまちなので、できる場合とできない場合があります。
ここからは、HTMLに直書きする方法とobjectタグで読み込む方法を例示します。
サンプルのデモ
以下は、円をクリックすると円の半径が大きくなるサンプルのデモです。
HTMLに直書きする方法
上記のサンプルをHTMLに直書きする場合は、以下のようになります。
<!-- sample.html --> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>SVGの練習</title> </head> <body> <svg width="200px" height="200px" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> <!-- 定義 --> <defs> <symbol id="c"> <circle cx="100" cy="100" r="50" id="circle"/> </symbol> </defs> <!-- 参照 --> <use href="#c" fill="navy"/> <!-- 処理 --> <script type="text/ecmascript"> const circle = document.getElementById('circle'); let size = circle.getAttribute("r")/1; const r = 10; circle.addEventListener('click', function(){ size += r; if(size > 100){ size = 50; } // console.log(size); circle.setAttribute("r", size); }); </script> </svg> </body> </html>
上記のようなコードは、可読性の観点からあまりよろしくありません。SVG、JavaScript、(CSS)をHTMLから分割して、別ファイルとして読み込むのが理想的だと考えます。
objectタグで読み込む方法1
HTMLからSVGを分割して、別ファイルにします。そして、objectタグでSVGを読み込みます。
<!-- sample.svg --> <svg width="200px" height="200px" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> <!-- 定義 --> <defs> <symbol id="c"> <circle cx="100" cy="100" r="50" id="circle"/> </symbol> </defs> <!-- 参照 --> <use href="#c" fill="navy"/> <!-- 処理 --> <script type="text/ecmascript"> const circle = document.getElementById('circle'); let size = circle.getAttribute("r")/1; const r = 10; circle.addEventListener('click', function(){ size += r; if(size > 100){ size = 50; } circle.setAttribute("r", size); }); </script> </svg>
SVGの中には、スタイルとJavaScriptが混在した状態です。
<!-- sample.html --> <object data="sample.svg" type="image/svg+xml"></object>
objectタグで読み込む方法2
SVGからJavaScriptを分割して、別ファイルにします。
<!-- sample.svg --> <svg width="200px" height="200px" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> <!-- 定義 --> <defs> <symbol id="c"> <circle cx="100" cy="100" r="50" id="circle"/> </symbol> </defs> <!-- 参照 --> <use href="#c" fill="navy"/> </svg>
JavaScriptを分割できましたが、スタイル(CSS)は残ったままです。
/* sample.js */ window.onload = function(){ const svgFig = document.getElementById('svgFig').contentDocument; const circle = svgFig.getElementById('circle'); let size = circle.getAttribute("r")/1; const r = 10; circle.addEventListener('click', function(){ size += r; if(size > 100){ size = 50; } circle.setAttribute("r", size); }); };
<!-- sample.html --> <object id="svgFig" data="sample.svg" type="image/svg+xml"></object> <script type="text/javascript" src="sample.js"></script>
分割したSVGファイルとJavaScriptファイルを読み込みます。
懸念点
SVGからスタイルを分割できていないのが残念です。