©️

自作したsvgアイコンをQuasarのQIconコンポーネントで表示する方法

2023/03/20に公開
Quasar vue pkg cli lang api setup
動作確認環境 v2.6.0 3.0.0 yarn vite ts composition <script setup>

IconComponent.vue
<template>
  <q-icon name="app:smile" color="grey-8" size="md" />
  <q-icon name="app:surprise" color="accent" size="4em" />
  <q-icon name="app:sleep" color="grey-8" size="md" />
  <q-icon name="app:enjoy" color="orange-7" size="xl" />
</template>

はじめに

Vue.jsのライブラリであるQuasarでは、様々なUIコンポーネントが提供されており、簡単にWebアプリケーションを作成することができます。その中でも、QIconコンポーネントはアプリケーションのアイコン表示を行うために便利なコンポーネントです。

この記事では、自作したsvgアイコンをQIconコンポーネントで表示する方法について解説します。
自作アイコンを使うことで、アプリケーションのブランドイメージを強化したり、ユーザーにとってわかりやすいアイコンを表示したりすることができます。

そしてそのアイコンの表示方法が、Quasarがサポートするアイコンセットの形式と同じやり方だと便利ですので、そのデータの作り方と呼び出し方も合わせて解説します。

本記事は、Vue.jsのQuasarを使用してWebアプリケーションを開発しているエンジニアや、アプリケーションのデザインに携わっているデザイナーにとって役に立つ内容となっています。

QIconとは

QIconは、Quasarで提供されているアイコン表示用コンポーネントです。QIconコンポーネントは、簡単にアイコンを表示することができ、アプリケーションのUIデザインを簡単にカスタマイズすることができます。

QIconコンポーネントでは、さまざまな形式のアイコンの表示に対応していますが、Quasarはすぐに使えるウェブフォントベースのアイコンセットをいくつか提供しており、自分が使いたいアイコンセットをquasar.config.jsに記述しておくだけで簡単に使いはじめることができます。以下は material-icons というアイコンセットを選んだ例です。

quasar.config.js
// ....
extras: [
  // ....
  'material-icons'
]

他にもアイコンセットがいくつか用意されていますので、詳しくは以下のドキュメントをご覧ください。
https://quasar.dev/vue-components/icon

使い方は、選んだアイコンセットが対応しているアイコンの名前をQIconコンポーネントで指定するだけです。この時に色やサイズを指定することもできます。

IconComponent.vue
<template>
  <q-icon name="delete" color="warning" size="xl" />
</template>

ここで自作したsvgアイコンを表示したい場合に、カスタムアイコンを用意する必要があります。
次の節では、カスタムアイコンを作成する方法について解説します。

カスタムアイコンを作成する

カスタムアイコンを使用する場合は、QIconコンポーネントに対応するアイコンファイルを用意する必要があります。
アイコンファイルとして使用できるフォーマットは、SVGやPNG、JPEGなどがありますが、SVGはベクター形式であるため、画像を拡大・縮小しても輪郭がぼやけないという点でおすすめです。

今回はSVG形式のアイコンファイルを作成した後に、ウェブフォントに変換して使う方法を紹介します。
ウェブフォントに変換することで色の変更などのスタイルの適用が容易になります。

大まかな流れを先に確認します。

  1. デザイン作成ツールでアイコンのデザインを作成する。
  2. svg形式で保存する。
  3. npmからウェブフォント変換ツールをインストールする。
  4. fantasticonコマンドで、svgファイルをウェブフォントに変換する。
  5. fantasticonコマンドをscriptsに登録しておく。

1. デザイン作成ツールでアイコンのデザインを作成する。

ペンツールとsvg形式のエクスポートに対応しているデザイン作成ツールであればなんでもよいと思いますが、Figma、illustrator、Inkscapeなどのツールで作成することができます。私は今回Inkscapeで簡単に4つのデザインを作ってみました。

smile surprise enjoy sleep

デザインができたらsvgファイルとして保存します。

2. svg形式で保存する。

svg形式でエクスポートします。svgのファイル名は今後アイコンを指定する際の名前になりますので、それを考慮して名前をつけます。以下の名前で保存しました。

  • smile.svg
  • surprise.svg
  • enjoy.svg
  • sleep.svg

3. npmからウェブフォント変換ツールをインストールする。

svgファイルをウェブフォントに変換する方法はいくつかあります。

  1. 変換サイトにsvgファイルをアップロードし、ウェブフォントをダウンロードする
  2. npmから変換ツールをローカルにインストールし、自分で変換する。

今回はやりませんでしたが、1の方法では、以下のサイトで変換することができます。
https://icomoon.io/

今回選んだ2の方法では、ツールがいくつかありましたので、トレンドを調べました。
https://npmtrends.com/fantasticon-vs-icon-font-buildr-vs-svgtofont

fantasticon がトレンドのようですので、fantasticonをインストールします。
グローバルインストールするか、プロジェクト内にインストールするかは、自由に選択してください。
今回はQuasarプロジェクトの下にfantasticonをインストールしましたので、Quasarプロジェクトのルートディレクトリで以下を実行します。

$ yarn add -D fantasticon

npmでパッケージ管理している場合は以下になります。

$ npm install --save-dev fantasticon

4. fantasticonで、svgファイルをwebフォントに変換する。

svgファイルを元に css , html , woff , woff2 を生成しますので、出力先ディレクトリを用意しておきます。

svgファイルは以下に置きました。
/src/custom-icons/svg/{svgファイル群}
出力先として、以下のディレクトリを作成しました。
/src/css/custom-icons

fantasticonを実行する前のQuasarプロジェクトにディレクトリは以下のようになりました。

.
├── README.md
├── index.html
├── node_modules/
├── package.json
├── quasar.config.js
├── src/
│   ├── App.vue
│   ├── css/
│   │   ├── app.scss
│   │   ├── custom-icons/     //この下に生成物が作成されます。
│   │   └── quasar.variables.scss
│   ├── custom-icons/
│   │   └── svg/                        //この下にsvg画像を置いておく。
│   │       ├── smile.svg
│   │       ├── sleep.svg
│   │       ├── enjoy.svg
│   │       └── surprise.svg
│   ├── layouts/
│   ├── pages/
│   ├── router/
│   └── stores/
├── tsconfig.json
└── yarn.lock

ではコマンドからfantasticonを実行して、ウェブフォントを作成します。以下のコマンドを実行します。

$ fantasticon src/custom-icons/svg \
-o src/css/custom-icons \
--normalize \
-t woff woff2 \
-g css html

↓以下のような結果が返ってきます。

Generating font kit...
✔ 4 SVGs found in src/custom-icons/svg
✔ Generated src/css/custom-icons/icons.woff
✔ Generated src/css/custom-icons/icons.woff2
✔ Generated src/css/custom-icons/icons.css
✔ Generated src/css/custom-icons/icons.html
Done

実行後は、以下のように4つのファイル icons.css , icons.html , icons.woff , icons.woff2 が生成されます。

.
├── README.md
├── index.html
├── node_modules
├── package.json
├── quasar.config.js
├── src/
│   ├── App.vue
│   ├── css/
│   │   ├── app.scss
│   │   ├── custom-icons/
│   │   │   ├── icons.css     //生成された
│   │   │   ├── icons.html   //生成された
│   │   │   ├── icons.woff   //生成された
│   │   │   └── icons.woff2 //生成された
│   │   └── quasar.variables.scss
│   ├── custom-icons/
│   │   └── svg/
│   │       ├── smile.svg
│   │       ├── sleep.svg
│   │       ├── enjoy.svg
│   │       └── surprise.svg
│   ├── layouts/
│   ├── pages/
│   ├── router/
│   └── stores/
├── tsconfig.json
└── yarn.lock

生成された /src/css/custom-icons/icons.html をブラウザで開くと以下のようなものが表示され、生成されたアイコンとアイコン名がセットになった一覧を確認することができます。

5. fantasticonコマンドをscriptsに登録しておく。

svgファイルを更新するたびに長いコマンドを実行するのは大変なので、 package.jsonscripts に書いておきます。

package.json
// ....
"scripts": {
    // ....
    "custom-icons": "fantasticon src/custom-icons/svg -o src/css/custom-icons --normalize -t woff woff2 -g css html"
  },

登録したscriptsを実行する場合は以下で実行することができます。

$ yarn run custom-icons

npmの場合は以下になります。

$ npm run custom-icons

これで、カスタムアイコンの生成が終わりました。
次の節では、QIconコンポーネントにカスタムアイコンを適用する方法について解説します。

QIconでカスタムアイコンを表示する

さきほど作成したカスタムアイコンをQIconに表示するまでの流れは以下のようになります。

  1. $q.iconMapFn() をオーバーライドしてカスタムマッピングを作成
  2. (Quasar CLIを使用している場合)fantasticonが生成したCSSファイルをアプリに追加
  3. QIconにnameを指定して表示

(※1と2は一度設定してしまえば、svgファイルに変更があっても更新する必要はありません。)

1. $q.iconMapFn() をオーバーライドしてカスタムマッピングを作成

QIconは、nameに文字が指定されると $q.iconMapFn 関数に従って表示するアイコンを決定します。
この関数をオーバーライドすることでカスタムマッピングを作成し、カスタムアイコンを呼び出すことができるようになります。
やり方を解説します。

オーバーライドする場所は /src/App.vue コンポーネントの created() フックが推奨と公式に書いてあるので、そこに記述を追加します。
(<script setup>記法を使用しており、vue3はcreated()フックがないため、公式とは書式が少し違いますが、やっていることは同じです。)

以下は、変更前の /src/App.vue です。

/src/App.vue(変更前)
<template>
  <router-view />
</template>

/src/App.vue を以下のように変更します。

/src/App.vue(変更後)
<template>
  <router-view />
</template>
<script setup lang="ts">
import { useQuasar } from 'quasar';
const $q = useQuasar();
$q.iconMapFn = (iconName) => {
  if (iconName.startsWith('app:') === true) {
    const name = iconName.substring(4);
    return {
      cls: 'icon-' + name,
    };
  }
};
</script>

$q.iconMapFn() の中身を解説します。
アイコン名が app: で始まっている場合、カスタムアイコンの独自のクラス名を返すように書き換えています。クラス名の命名ルールが 'icon-' + name となっているのは fantasticon が生成するcssがそうなっているため、それに合わせました。
この関数は、何もマッチせず返り値を何も返さなかった場合、デフォルトのQuasarアイコンマッピングに引き継がれます。

カスタムマッピングの詳細は公式ドキュメントにも詳しく書かれていますのでご覧ください。
https://quasar.dev/vue-components/icon#custom-mapping

2. (Quasar CLIを使用している場合)fantasticonが生成したCSSファイルをアプリに追加

Quasar CLIを使用している場合は、 quasar.config.js にfantasticonが生成したCSSファイルを追加します。 /src/css/ より下のパスを書きます。

quasar.config.js
// ....
css: [
  // ....
  'custom-icons/icons.css'
]

これで全ての準備が整いました。あとはQIconにnameで指定するだけとなりました。

3. QIconにnameを指定して表示

全ての準備を終えたカスタムアイコンをQIconコンポーネントで表示するには、以下のように name の先頭を app: にして、その後ろにカスタムアイコン名を指定するだけです。

<template>
  <q-icon name="app:smile" />
</template>

便利だと思うところ

以下サンプルコードのように、 icons の各 name は、 deletemail はマテリアルアイコンですが、その他の app:smile app:surprise app:sleep app:enjoy はカスタムアイコンです。
1つの配列にごちゃまぜになっているのですが、それを意識せずに統一されたQIconコンポーネントとして扱えるのが便利だと思っています。

IconComponent.vue
<template>
  <q-icon
    v-for="(icon, i) in icons"
    :key="i"
    :name="icon.name"
    :color="icon.color"
    :size="icon.size"
  />
</template>
<script setup lang="ts">
const icons = [
  { name: 'delete',       color: 'black',  size: 'lg' },
  { name: 'app:smile',    color: 'black',  size: 'lg' },
  { name: 'mail',         color: 'red',    size: 'lg' },
  { name: 'app:surprise', color: 'accent', size: 'sm' },
  { name: 'app:sleep',    color: 'blue-8', size: 'lg' },
  { name: 'app:enjoy',    color: 'pink-4', size: 'md' },
];
</script>

まとめ

本記事では、自作したsvgアイコンをQuasarのQIconコンポーネントで表示する方法を説明しました。svgファイルからウェブフォントに変換することで、マテリアルアイコンなどQuasarがサポートしているアイコンと、形式を合わせることができ、さらに便利に使うことができるようになりました。

カスタムアイコンで使用するsvgが自作のものでない場合は、著作権やライセンスについては十分に注意する必要があります。

レスキューナウテックブログ

Discussion