2024/08/15

[Vuetify3] custom icon を追加する

公式の説明が少し分かりづらいのですが、Vuetify3 には icon の設定方法が2つ1あります。

  • 「MDI - CSS」は全 MDI fornt を一括でインストールする方法
  • 「MDI - JS SVG」は必要な font だけをインストールする方法

当然、後者の方が効率も良いしお勧めなのですが、公式が書いていないメリットがもう一つあります。

「MDI - JS SVG」の方は custom icon の表示が超楽なのです。

そもそも「追加」する必要がない

「MDI - JS SVG」は "MDI" と書いてありますが、実はほとんど Material Design Icon とは関係がありません。
この Icon Set2 は与えられた文字列を path として svg icon として描画する機能を提供しています。
簡単に言ってしまえば、1 path の svg であれば何でもオーケーなのです3

論より証拠。 まずはやってみましょう。公式に書いてあるように mdi icon set を使用するようにします。

1
2
3
4
5
6
7
8
9
10
11
12
import { createVuetify } from 'vuetify'
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg'
 
export default createVuetify({
  icons: {
    defaultSet: 'mdi',
    aliases,
    sets: {
      mdi,
    },
  },
})

その後、以下のように SVG の path 情報をベタ書き。

1
2
3
<template>
  <v-icon icon="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z"></v-icon>
</template>

これで、以下のようにアイコンが表示されます。

実際、 @mdi/js の中身を見てみると、以下のように string 情報が羅列されているだけです。

1
2
3
4
export var mdiAbTesting = "M4 2A2 2 0 0 0 2 4V12H4V8H6V12H8V4A2 2 0 0 0 6 2H4M4 4H6V6H4M22 15.5V14A2 2 0 0 0 20 12H16V22H20A2 2 0 0 0 22 20V18.5A1.54 1.54 0 0 0 20.5 17A1.54 1.54 0 0 0 22 15.5M20 20H18V18H20V20M20 16H18V14H20M5.79 21.61L4.21 20.39L18.21 2.39L19.79 3.61Z";
export var mdiAbacus = "M5 5H7V11H5V5M10 5H8V11H10V5M5 19H7V13H5V19M10 13H8V19H10V17H15V15H10V13M2 21H4V3H2V21M20 3V7H13V5H11V11H13V9H20V15H18V13H16V19H18V17H20V21H22V3H20Z";
export var mdiAbjadArabic = "M12 4C10.08 4 8.5 5.58 8.5 7.5C8.5 8.43 8.88 9.28 9.5 9.91C7.97 10.91 7 12.62 7 14.5C7 17.53 9.47 20 12.5 20C14.26 20 16 19.54 17.5 18.66L16.5 16.93C15.28 17.63 13.9 18 12.5 18C10.56 18 9 16.45 9 14.5C9 12.91 10.06 11.53 11.59 11.12L16.8 9.72L16.28 7.79L11.83 9C11.08 8.9 10.5 8.28 10.5 7.5C10.5 6.66 11.16 6 12 6C12.26 6 12.5 6.07 12.75 6.2L13.75 4.47C13.22 4.16 12.61 4 12 4Z";
...省略

カスタムアイコンを使用する方法

というわけで、結論としては以下のように path 情報を提供するファイルを生成して、

customIcons.ts
1
export const customMyIcon = 'M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z';

@mdi/js と同様に使用してあげれば OK です。

1
import {customMyIcon} from '@/icons'
1
2
3
<template>
<v-icon :icon="customMyIcon"></v-icon>
</template>

ただし、このとき生成される svg タグは 24 x 24 (ViewBox も) なので注意が必要です。 path 情報も 24 x 24 で生成しておかねばなりません。

複数 path や ViewBox のサイズが違う場合どうしたら良いのか?

まず、単色であれば 単一 path に変換してあげたほうが良いでしょう。
そうすることで、色を後から変えることができます。

また、サイズも 24 x 24 に変換したものを使うのが良いかと思います。

それでも、複雑な svg を表示したい。という場合4は、以下のようにsvg タグを実装したカスタムコンポーネントを用意しましょう。 このとき、class="v-icon__svg" を加えることで、アイコンの特性をもたせることができます。ただし、この class 名は将来的に変わる可能性もあるので要注意です。

CustomMyIcon.vue
1
2
3
4
5
<tamplate>
  <svg class="v-icon__svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
    <!-- svg 実装-->
  </svg>
</tamplate>

以下のようにコンポーネントを直接 :icon に渡した場合、アイコンサイズで表示してくれます。

1
import CustomMyIcon from '@/CustomMyIcon.vue'
1
2
3
<template>
<v-icon :icon="CustomMyIcon"></v-icon>
</template>
  1. 「MDI - CSS」と「MDI - JS SVG」の2つです。「Icon Search」は単なる便利ツールなのでご注意を。 
  2. Setと言っていいのか? 
  3. 正確には Vuetify の中で使用されているいくつかの icon をセットとして提供しています 
  4. もう、それアイコンじゃないよね、という話も… 
?

0 件のコメント: