はじめに
今回は、1つのSVGファイルに複数のアイコン画像をまとめてみようと思います。
1つにまとめることで、
- 全体としてSVGファイルのサイズが小さくなりそうなこと
- HTMLとSVG読み込み時に読み込みファイル数が減ること
- 1つのアイコンに色々なものを準備してバリエーションをもたすことができること(例:ホームアイコンの種類を複数作るみたいなイメージ)
- および、一部のSVG読み込みできず、一部のアイコンだけ表示されないことを防ぐことができること
など、まとめたほうがよいことがあるのかなと思いました。
この4つ目の利点については、第20回 JavaScript モーダルサイドバーの共通化でサイドバーを作成した時に、アイコンをで作ろうと思ったときにSVGで作成すれば、ひとつにまとめらえるなと考えていました。
ということで、この20回のソースを使用してアイコンを設定していきます。
今回実施する内容
これまでに作成した以下のアイコン画像を1つのSVGファイルにまとめます。さらにそれをサイドバーに実装します。
- ハンバーガーアイコン(第2回 SVG ハンバーガーアイコン+hover)
- ホームアイコン(第4回 SVG ホームアイコンの作成とhoverによる色変え)
- マイページアイコン(第6回 SVG マイページアイコンの作成)
ソースコード(Git Hub)
環境
OS: Windows 11 JP (64bit)
Edge: バージョン 140.0.3485.81 (公式ビルド) (64 ビット)
参考
- 第2回 SVG ハンバーガーアイコン+hover
- 第4回 SVG ホームアイコンの作成とhoverによる色変え
- 第6回 SVG マイページアイコンの作成
- 第20回 JavaScript モーダルサイドバーの共通化
用語
基本(ソースは01フォルダ)
ファイル試合はシンプルです。
menu.htmlからmenuIcon.svgを読み込んで、3つのアイコンをIDを指示して表示させます。
<div id="menuIcon">
<svg width="48px" height="48px">
<use xlink:href="menuIcon.svg#hamburgerIcon"></use>
</svg>
</div>
<div id="homeIcon">
<svg width="48px" height="48px">
<use xlink:href="menuIcon.svg#homeIcon"></use>
</svg>
</div>
<div id="myPageIcon">
<svg width="48px" height="48px">
<use xlink:href="menuIcon.svg#myPageIcon"></use>
</svg>
</div>
<?xml version="1.0" standalone="no"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="hamburgerIcon" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path d="M9 10 L24 10" stroke="black" stroke-width="2" />
<path d="M9 16 L24 16" stroke="black" stroke-width="2" />
<path d="M9 22 L24 22" stroke="black" stroke-width="2" />
</symbol>
<symbol id="homeIcon" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path d="M16 7 L17 7 L26 16 L26 17 L23 17 L23 26 L18 26 L18 20 L15 20 L15 26 L10 26 L10 17 L7 17 L7 16 z"/>
</symbol>
<symbol id="myPageIcon" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="12" r="6" fill="none" stroke-width="2" stroke="#000" />
<path d="M 8 25 a 8 7 0 1 1 16 0" stroke-width="2" fill="none" stroke="#000" />
</symbol>
<defs>
</svg>
menu.htmlの内容
use要素を使用して、`menuIcon.svgの各IDを呼び出すように設定するだけです。
menuIcon.svgの説明
今回は、defs要素を使用して最初にまとめました。defs要素自体は設定しなくても、今回の動作に何の影響を与えることはありませんが、定義の場所を明確化するために使用するもののようなので、従いました。
defs要素の配下は、symbol要素を使用して、symbol要素の配下に各アイコンの内容を記載しました。
アイコンの内容は、「参考」にも記載した過去の記事を参照ください。
サイドバーと組み合わせる(ソースは02フォルダ)
第20回 JavaScript モーダルサイドバーの共通化では、Webサイトでよく使われるサイドバーを作りました。
違いは、sideBar.js部分であるため、ここを紹介します。
window.addEventListener("DOMContentLoaded", () => {
let strHtml = `\n`;
strHtml += `\t<svg class="menuIcon" id="menuIcon">\n`;
strHtml += `\t\t<use xlink:href="menuIcon.svg#hamburgerIcon" />\n`;
strHtml += `\t</svg>\n`;
strHtml += `\t<div id="sideBar">\n`;
strHtml += `\t\t<svg class="menuIcon" id="menuIcon2">\n`;
strHtml += `\t\t\t<use xlink:href="menuIcon.svg#hamburgerIcon" />\n`;
strHtml += `\t\t</svg>\n`;
strHtml += `\t\t<div id="menuList">\n`;
strHtml += `\t\t\t<div id="home" class="menuItem">\n`;
strHtml += `\t\t\t\t<svg width="48px" height="48px">\n`;
strHtml += `\t\t\t\t\t<use href="menuIcon.svg#homeIcon" />\n`;
strHtml += `\t\t\t\t</svg>ホーム</div>\n`;
strHtml += `\t\t\t<div id="mypage" class="menuItem">\n`;
strHtml += `\t\t\t\t<svg width="48px" height="48px">\n`;
strHtml += `\t\t\t\t\t<use href="menuIcon.svg#myPageIcon" />\n`;
strHtml += `\t\t\t\t</svg>マイページ</div>\n`;
strHtml += `\t\t</div>\n`;
strHtml += `\t</div>\n`;
strHtml += `\t<div id="cover" class="cover"></div>\n`;
menuSideBar.insertAdjacentHTML("beforeend", strHtml);
window.addEventListener("DOMContentLoaded",...の部分が、画面読み込み時に処理される内容です。
strHtmlがサイドバーを読み込みするためのHTMLを文字列で記載したものです。
第回との違いを示しながら説明します。
メニューアイコン(ハンバーガーアイコン)
strHtml += `\t<img src="humbergerIcon.svg" id="menuIcon" class="menuIcon"/>\n`;
これが、↓のように。
strHtml += `\t<svg class="menuIcon" id="menuIcon">\n`;
strHtml += `\t\t<use xlink:href="menuIcon.svg#hamburgerIcon" />\n`;
strHtml += `\t</svg>\n`;
元々はimg要素からhumbergerIcon.svgを呼び出していましたが、今回はsvg要素を使用してアイコンをまとめたmenuIcon.svgを使用して#hamburgerIconを呼び出しています。
どうでもよいですが、ハンバーガーのスペルが間違っていたため、今回は修正しました。
サイドバーのメニュー
strHtml += `\t\t<img src="humbergerIcon.svg" id="menuIcon2" class="menuIcon"/>\n`;
strHtml += `\t\t<div id="menuList">\n`;
strHtml += `\t\t\t<div id="home" class="menuItem">ホーム</div>\n`;
strHtml += `\t\t\t<div id="mypage" class="menuItem">マイページ</div>\n`;
strHtml += `\t\t</div>\n`;
これが、↓のように。
strHtml += `\t\t<svg class="menuIcon" id="menuIcon2">\n`;
strHtml += `\t\t\t<use xlink:href="menuIcon.svg#hamburgerIcon" />\n`;
strHtml += `\t\t</svg>\n`;
strHtml += `\t\t<div id="menuList">\n`;
strHtml += `\t\t\t<div id="home" class="menuItem">\n`;
strHtml += `\t\t\t\t<svg width="48px" height="48px">\n`;
strHtml += `\t\t\t\t\t<use href="menuIcon.svg#homeIcon" />\n`;
strHtml += `\t\t\t\t</svg>ホーム</div>\n`;
strHtml += `\t\t\t<div id="mypage" class="menuItem">\n`;
strHtml += `\t\t\t\t<svg width="48px" height="48px">\n`;
strHtml += `\t\t\t\t\t<use href="menuIcon.svg#myPageIcon" />\n`;
strHtml += `\t\t\t\t</svg>マイページ</div>\n`;
strHtml += `\t\t</div>\n`;
元々はホームやマイページにアイコン事態存在しなかったため、アイコンを設定するようにしました。
今回作成したmenuIcon.svgにIDを設定して読み出すようにしています。
ハンバーガーアイコンのSVG要素ではwidthやheihgt属性を設定していませんでしたが、ホームやマイページのSVGでは設定しました。これは、少し理由があり、ハンバーガーアイコンでは、sideBar.cssの.menuIconで、widthとheightを設定しているため、sideBar.js上で設定しなくてもサイズが確定できているのに対して、新たに作成したホームやマイページではCSSがないため、sideBar.js上でwidthとheightを設定する必要性がありました。
設定をCSS上に持っていくことも可能ですが、今回の説明であまり関係のない設定をほかのファイルに波及するのを避けたかったためこのようにしました。
が、後述する部分で結局CSSファイルを直してしまったのですが・・・
sideBar.cssの修正
CSSを変更せずに実装すると以下のようにアイコンと文字が上下中央に合わなかったため、CSSを一か所修正しました。

.menuItem {
width: 180px;
display:flex;
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
padding-bottom: 10px;
align-items: center;
height: 48px;
.menuItemにdisplay:flexとalign-items:centerを追加しました。
おわりに
複数のアイコン画像を1つのSVGにまとめてみました。
また、サイドバー上のメニューにそのアイコンを設定しました。
第20回のサイドバーの記事は2024年9月投稿だったため、ほぼ一年かけて、やりたかったことを実装できたなという感じでした。
今回の修正では、widthやheightがsideBar.jsに含まれており、当時の作った感じだと画面の調整はCSSで実施するという方針だったと思うので、その辺はそのうち直したいと思います。



