✏️
SVG形式アイコンをコンポーネント化した
はじめに
sweeep株式会社でエンジニアをしている、いまふくです。
新サービス「sweeep Box」では、Phosphor Icons からSVGをコピーし、アイコンとして使用しています。SVGタグをそのまま使用すると扱いづらい部分があったため、アイコンのコンポーネント化を行いました。
SVGとは
SVG(Scalable Vector Graphics)は画像フォーマットの一種です。
html, cssなどと同じく「タグ」で扱うことができます。
メリット
- 拡張性・汎用性が高い
後から色・サイズ・文字の変更が簡単
アニメーションをつけることも可能 - 拡大縮小による画像の劣化がない
画像や文字などの2次元情報を数値化して記録していて、ブラウザがその場で描画する - ファイルサイズが軽い(特にアイコンなどシンプルなもの)
デメリット
- コードを見ただけでは何を描画しているかがわからない
- 写真など複雑な配色や輪郭の画像描写は、pngやjpgよりファイルサイズが大きくなる
コンポーネント化した
「コードを見ただけでは何を描画しているかがわからない」デメリットの解消、さらにサイズや色などをより簡単に指定・変更できるように、コンポーネント化を行いました。
編集可能な SVG アイコンシステム — Vue.js を参考に実装しています。
環境
@nuxt/cli v2.15.8
手順
-
使用するアイコンのSVGファイルを保存する
regularとfilledを1つのファイルに保存し、propsの値により表示内容を出し分けます。
可変にしたい項目(strokeやstroke-widthなど)は削除しています。components/svg/Eye.vue<template> <g v-if="filled"> <path d="M247.3,124.8c-.3-.8-8.8-19.6-27.6-38.5C194.6,61.3,162.9,48,128,48S61.4,61.3,36.3,86.3C17.5,105.2,9,124,8.7,124.8a7.9,7.9,0,0,0,0,6.4c.3.8,8.8,19.6,27.6,38.5C61.4,194.7,93.1,208,128,208s66.6-13.3,91.7-38.3c18.8-18.9,27.3-37.7,27.6-38.5A7.9,7.9,0,0,0,247.3,124.8ZM128,92a36,36,0,1,1-36,36A36,36,0,0,1,128,92Z" ></path> </g> <g v-else> <path d="M128,56C48,56,16,128,16,128s32,72,112,72,112-72,112-72S208,56,128,56Z" fill="none" stroke-linecap="round" stroke-linejoin="round" ></path ><circle cx="128" cy="128" r="40" fill="none" stroke-linecap="round" stroke-linejoin="round" ></circle> </g> </template> <script> import { defineComponent } from '@vue/composition-api' export default defineComponent({ props: { filled: { type: Boolean, default: false, }, }, }) </script>
-
スロットを使うベースアイコン(IconBase.vue)コンポーネントを作成する
IconBase.vue<template> <svg xmlns="http://www.w3.org/2000/svg" :width="size" :height="size" :viewBox="viewBox" :class="addClass" :stroke="color" :stroke-width="filled ? '0' : weight" :fill="filled ? color : ''" > <slot /> </svg> </template> <script> import { defineComponent } from '@vue/composition-api' export default defineComponent({ props: { size: { type: Number, default: 20, }, color: { type: String, default: '#000000', }, weight: { type: Number, default: 16, }, filled: { type: Boolean, default: false, }, addClass: { type: String, default: '', }, viewBox: { type: String, default: '0 0 256 256', }, }, }) </script>
-
実際に使用する
parent.vue<icon-base :size="12" color="red" class="animate-spin" > <eye /> </icon-base>
おわりに
SVG形式ファイルをより分かりやすく扱う方法をご紹介しました。
最後に宣伝になりますが、弊社ではエンジニアを募集しています。ご興味のある方は下記リンクよりご応募お待ちしております!
Discussion