こんにちは。きんくまです。
イラレから書き出したSVGのデータをhtmlに取り込む方法はいろいろとあります。
外部SVGを非同期で読み込んだりとか。
でも今回は、JSにSVGを静的に埋め込んで、パースしたSVGを使いたいです。
JSにSVGを埋め込む
埋め込むといっても、ES6のヒアドキュメントを使えば簡単です。
イラレから書き出したSVGには id とか title とか入っているので消しておきました。あと下のデータめっちゃ適当です。
export const SVGData = ` <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 768"> <rect x="131" y="121" width="637" height="449" fill="#29abe2" stroke="#000" stroke-miterlimit="10" stroke-width="10"/> <circle cx="536" cy="229" r="163" fill="#ff0" stroke="red" stroke-miterlimit="10" stroke-width="10"/> <polygon points="262 81 323 221 501 212 496 481 262 459 78 443 261 345.5 262 81" fill="#006837" stroke="#7ac943" stroke-miterlimit="10" stroke-width="10"/> <path d="M381,490c41.18-56.62,118-136,171-42s101,52,136,24l46,70s-180,35-255,17S341,545,381,490Z" fill="blue" stroke="#7ac943" stroke-miterlimit="10" stroke-width="10"/> </svg> `;
slackとか、markdownみたいに バッククォートを3個書いてうまくいかなかったのはナイショです。
ヒアドキュメントは1個で良かったです。
パースしてhtml側のSVGに入れる
サンプルのhtmlを用意して、この中にさきほど埋め込んだSVGを入れたいです。
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" id="sample_svg" width="600" height="600"> </svg>
文字列から動的にSVGを生成するにはDOMParserを使えばいいみたい。
>> Create an SVG DOM element from a String
>> Parsing an SVG or HTML document
それでポイントとしては、DOMParserで返ってくるオブジェクトはルートがDocumentになっているので、一番上の子供のSVGを取得する必要があることです。
const svgText = SVGData; const domParser = new DOMParser(); const parsedSVGDoc = domParser.parseFromString(svgText, 'image/svg+xml'); const parsedSVG = parsedSVGDoc.childNodes[0]; //htmlのSVG const svg = document.querySelector('#sample_svg'); //生成したSVGをhtmlにそのまま入れる svg.appendChild(parsedSVG);
この場合は、htmlのSVGの中に、生成したSVGが入れ子で入っている状態です。(SVGふたつ)
生成したSVGの中の一部を使って中身を変えたい
さきほどは生成したSVGをそのまま入れましたけど、SVGなのでツリー構造になっているから、一部の塗りだけを変更したりとか、一部分だけを移植したりとかいろいろできます。
const svgText = SVGData; const domParser = new DOMParser(); const parsedSVGDoc = domParser.parseFromString(svgText, 'image/svg+xml'); const parsedSVG = parsedSVGDoc.childNodes[0]; const svg = document.querySelector('#sample_svg'); //ここまで同じ ===== //IE11だと querySelectorAll のあとのforEachができないから polyfill //https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach if (window.NodeList && !NodeList.prototype.forEach) { NodeList.prototype.forEach = function (callback, thisArg) { thisArg = thisArg || window; for (var i = 0; i < this.length; i++) { callback.call(thisArg, this[i], i, this); } }; } //やりたいことはここから === //元データから塗りが青だけのpathを取り出して const blueFillPaths = parsedSVG.querySelectorAll('path[fill="blue"]'); //塗りを赤にして、そのpathだけhtmlに埋め込む blueFillPaths.forEach((path)=>{ path.setAttribute('fill', '#ba82de'); svg.appendChild(path); });
この場合は、htmlのSVGの中に、生成したSVGから移植した一部のNodeが入っている状態です。(SVGひとつ)
SVGを使ってグラフやツールを作ってるのですが、Retina対応とか考えなくてもきれいに見えるのでSVGは便利だと思いますです。(IE11でも動く)
グラフはd3.js、ツールはvue.jsとそれぞれ組み合わせてやっています。
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ