iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
Vue.js

Nuxt 3 實戰筆記系列 第 22

[Day 22] Nuxt 3 使用 SVG 的解決方案與更方便的使用 Icon 圖示

  • 分享至 

  • xImage
  •  

前言

網站的介面多多少少會放置圖示 (Icon),圖示的載入方式可以像圖片一樣以 png、jpg、webp 或 svg 等圖片格式來呈現,本篇將介紹如何在 Nuxt 中使用 svg 圖片及使用第三方模組套用豐富的 Icon 圖示。

可縮放向量圖形 (Scalable Vector Graphics, SVG)

使用 svg 圖示的優點:

  • 向量圖形可以調整成任意大小且不失真的圖形
  • 如果你熟悉結構語法,圖形線條與樣式可以直接編輯 XML
  • 可以套用 CSS 樣式設定顏色或濾鏡效果
  • 可以產生動畫效果的圖形

更多人會選擇的是 svg 是因為在實務上圖示可能需要以各種不同的大小或能適應 CSS 樣式的調整,如圖示與文字相同的顏色變化效果,而以字型來呈現的圖示甚至直接用 CSS 或 JS 手刻都較 png 或 jpg 這類像素類型的圖片更多的可玩性。

Nuxt 3 使用 SVG

首先,準備一個 SVG 圖形檔案,建立於 ./assets/svg/nuxt.svg,接下來我們就可以在元件中分別以不同方式做使用。

靜態資源連結

如同圖片的使用方式,我們可以直接使用 src 來載入圖形。

<template>
  <img src="~/assets/svg/nuxt.svg" />
</template>

使用 SVG 標籤描述

你也可以選擇直接使用 SVG 的內容以 HTML 標籤形式來描述 SVG 圖形。

<template>
  <svg xmlns="http://www.w3.org/2000/svg" width="48.77" height="32" viewBox="0 0 256 168">
    <path fill="#00DC82" d="M143.618 167.029h95.166c3.023 0 5.992-.771 8.61-2.237a16.963 16.963 0 0 0 6.302-6.115a16.324 16.324 0 0 0 2.304-8.352c0-2.932-.799-5.811-2.312-8.35L189.778 34.6a16.966 16.966 0 0 0-6.301-6.113a17.626 17.626 0 0 0-8.608-2.238c-3.023 0-5.991.772-8.609 2.238a16.964 16.964 0 0 0-6.3 6.113l-16.342 27.473l-31.95-53.724a16.973 16.973 0 0 0-6.304-6.112A17.638 17.638 0 0 0 96.754 0c-3.022 0-5.992.772-8.61 2.237a16.973 16.973 0 0 0-6.303 6.112L2.31 141.975a16.302 16.302 0 0 0-2.31 8.35c0 2.932.793 5.813 2.304 8.352a16.964 16.964 0 0 0 6.302 6.115a17.628 17.628 0 0 0 8.61 2.237h59.737c23.669 0 41.123-10.084 53.134-29.758l29.159-48.983l15.618-26.215l46.874 78.742h-62.492l-15.628 26.214Zm-67.64-26.24l-41.688-.01L96.782 35.796l31.181 52.492l-20.877 35.084c-7.976 12.765-17.037 17.416-31.107 17.416Z"/>
  </svg>
</template>

使用 Nuxt Icon 模組來建立圖示

在沒有設計稿進行網站開發時,許多時候需要自己尋找圖示來設計介面,傳統的方式需要一一下載圖片或複製標籤描述來建立我們所需要的圖示,在使用上就會花上不少時間。

網路上有許多免費且開源的圖示或字型可以做使用,而 Nuxt Icon 模組也是選擇之一,模組中不僅整合了 Iconify 的 Icon 圖示集,只要在 Nuxt 中安裝後,我們只要宣告標籤與圖示名稱,就可以很方便的來載入圖示。

安裝與使用的步驟

Step 1. 安裝套件

安裝 Nuxt Icon 模組。

npm install -D nuxt-icon

Step 2. 配置使用模組

在 ./nuxt.config.ts 中的 modules 屬性,添加 Nuxt Icon 模組的名稱 nuxt-icon

export default defineNuxtConfig({
  modules: ['nuxt-icon']
})

Step 3. 開始使用

至此,我們就可以在頁面或元件中使用,為模組所提供的 <Icon> 元件來建立圖示,這個 Icon 元件可以傳入 name 屬性,以此來顯示不同的 Icon 圖示,size 則可以控制圖示的大小。

<Icon name="logos:nuxt" size="360" />

就是這麼簡單,我們就能使用內建的 SVG 圖示。

https://ithelp.ithome.com.tw/upload/images/20231007/20152617nssuRqEnIb.png

Iconify 圖示集

在使用模組所提供的元件 Icon 時,需要傳入一個 name 的屬性,這個屬性是 Iconify 圖示集所定義的,Iconify 提供多達 100,000 個以上的圖示,並具有多種風格類型的系列圖示,在這個網站 https://icones.js.org/ 可以快速搜尋到你想要的圖示與對應的圖示名稱 name

例如我想要在 Fluent UI System Icons 集合內,如下圖,點擊欲使用圖示,就會跳出提示,包含元件所需要的 name 屬性值 fluent:airplane-take-off-24-regular 或其他載入方式。

https://i.imgur.com/Jz16dcK.gif

透過元件的 name 屬性值,我們就能快速的添加圖示到頁面或元件之中。

<Icon name="fluent:airplane-take-off-24-regular" />

Emoji

Icon 元件也可以使用 Emoji 來當作 name 屬性值,以此來使用元件參數控制 Emoji 。

<Icon name="🚀" /> 

Vue 元件

透過模組約定的元件目錄 ./components/global,你也可以使用自訂的 SVG 來建立圖示,建立一個圖示元件 ./components/global/NuxtIcon.vue 內容如下。

<template>
  <svg xmlns="http://www.w3.org/2000/svg" width="48.77" height="32" viewBox="0 0 256 168">
    <path fill="#00DC82" d="M143.618 167.029h95.166c3.023 0 5.992-.771 8.61-2.237a16.963 16.963 0 0 0 6.302-6.115a16.324 16.324 0 0 0 2.304-8.352c0-2.932-.799-5.811-2.312-8.35L189.778 34.6a16.966 16.966 0 0 0-6.301-6.113a17.626 17.626 0 0 0-8.608-2.238c-3.023 0-5.991.772-8.609 2.238a16.964 16.964 0 0 0-6.3 6.113l-16.342 27.473l-31.95-53.724a16.973 16.973 0 0 0-6.304-6.112A17.638 17.638 0 0 0 96.754 0c-3.022 0-5.992.772-8.61 2.237a16.973 16.973 0 0 0-6.303 6.112L2.31 141.975a16.302 16.302 0 0 0-2.31 8.35c0 2.932.793 5.813 2.304 8.352a16.964 16.964 0 0 0 6.302 6.115a17.628 17.628 0 0 0 8.61 2.237h59.737c23.669 0 41.123-10.084 53.134-29.758l29.159-48.983l15.618-26.215l46.874 78.742h-62.492l-15.628 26.214Zm-67.64-26.24l-41.688-.01L96.782 35.796l31.181 52.492l-20.877 35.084c-7.976 12.765-17.037 17.416-31.107 17.416Z"/>
  </svg>
</template>

我們就可以在頁面或元件中,使用 Icon 元件並傳入建立的元件名稱作為 name 屬性值。

<Icon name="NuxtIcon" />

圖示載入的方式

Nuxt Icon 模組所使用的載入方式,是透過發出 HTTP 請求 Iconify CDN 來載入圖示,雖然模組提供 CDN 與 Local Storage 快取的方式來解決請求速度的問題,但是模組的圖示在網站打包或建立靜態網站時,並沒有辦法在建構時期一同把包並提供離線使用,所以可能會發生圖示未載入完成前的空白狀態或需要可以接受網路的環境。

至今仍然有部分使用者仍希望可以預渲染或預先請求圖示資源,模組的主要維護者 Sébastien Chopin 目前有考慮使用 unplugin 插件來支援,但目前尚無相關規劃,只能靜待版本功能推進或貢獻者來完善這個小缺點了。

更多 Nuxt Icon 的使用方式與配置,可以參考官方文件

按需載入圖示的 unplugin-icons 模組

前面介紹了 Nuxt Icon 的模組,最後提到了一個小缺點就是沒有辦法將圖示打包,接下來要介紹的模組 unplugin-icons 不僅能解決該問題而且同樣也是支援 Iconify 圖示集,接下來就來介紹安裝與使用。

安裝與使用的步驟

Step 1. 安裝套件

安裝 unplugin-icons 模組。

npm install -D unplugin-icons

Step 2. 安裝 Iconify 圖示集

你有兩種安裝方式可以選擇:

a. 安裝完整的集合,雖然比較大包,但是生產環境也僅會打包實際使用到的圖示

npm i -D @iconify/json

b. 僅安裝特定圖標集,例如欲安裝 Material Design Icons 圖標集,支援的圖標集列表可以參考官方 API

npm i -D @iconify-json/mdi

Step 3. 配置使用模組

在 ./nuxt.config.ts 中的 modules 屬性,添加 Nuxt Icon 模組的名稱 unplugin-icons/nuxt

export default defineNuxtConfig({
  modules: ['unplugin-icons/nuxt']
})

Step 4. 開始使用

我們於頁面或元件中使用時,需要先 import 所需要使用的圖示,才能使用圖示元件。

<template>
  <IconAirplaneTake :style="{ fontSize: '360px' }"/>
</template>

<script setup>
import IconAirplaneTake from '~icons/fluent/airplane-take-off-24-regular'
</script>

SSR 與 SSG 友好

unplugin-icons 它其中一個特性就是它能夠將圖示與頁面一起渲染,如下圖在首次請求,頁面或元件中所使用到的圖示,無須在客戶端發送請求來載入圖示,

https://ithelp.ithome.com.tw/upload/images/20231007/20152617Xwx0wS6Ywb.png

自動導入

Nuxt 3 本身就具備自動導入的特性,unplugin-icons 模組也可以啟用自動導入的功能,雖然步驟有點繁瑣,但設定完成後也能幫助能省去需要撰寫 import 的時間。

Step 1. 安裝插件

npm install -D unplugin-vue-components

Step 2. 調整配置

在 ./nuxt.config.ts 中,載入 IconsResolverIconsComponents,並添加 vite 插件來解析元件,同時我們也設定元件的前綴名稱為 icon

import IconsResolver from 'unplugin-icons/resolver'
import Icons from 'unplugin-icons/vite'
import Components from 'unplugin-vue-components/vite'

export default defineNuxtConfig(async () => ({
  modules: [
    ['unplugin-icons/nuxt']
  ],
  vite: {
    plugins: [
      Components({
        resolvers: [IconsResolver({
          prefix: 'icon'
        })]
      }),
      Icons({})
    ]
  }
}))

Step 3. 開始使用

使用具自動導入的圖示元件時你必須遵循元件名稱格式才能正確的推斷及載入圖示。

自動導入圖示的元件名稱格式:

{prefix}-{collection}-{icon}

prefix: 我們設定為 icon

collection: 對應 Iconify 圖示集 ID。

icon: 圖示集的 Icon 名稱。

例如欲使用 Fluent UI System Icons 圖標集的圖示 airplane-take-off-24-regular,使用起來如下程式碼:

<template>
  <!-- <IconAirplaneTake :style="{ fontSize: '360px' }"/> -->
  <icon-fluent-airplane-take-off-24-regular :style="{ fontSize: '360px' }" />
  <IconFluentAirplaneTakeOff24Regular :style="{ fontSize: '360px' }" />
</template>

<script setup>
// import IconAirplaneTake from '~icons/fluent/airplane-take-off-24-regular'
</script>

如果你是在 https://icones.js.org/ 挑選圖示,那麼提示的圖示名稱例如為 fluent:airplane-take-off-24-regular,分號前的 fluent 即是對應元件格式的 collectionairplane-take-off-24-regular 即是對應元件格式的 name

更多 unplugin-icons 的使用方式與配置,可以參考官方文件

UnoCSS - Preset-icons

如果你有使用 UnoCSS,那麼 @unocss/preset-icons 插件應該會是最好的選擇,同樣使用 Iconify 圖示集,並且使用類別名稱 (class) 來建立圖示。

不使用 UnoCSS 全部功能,只啟用 Preset-icons

如果你本身使用的是其他 CSS 框架語言,如 Tailwind CSS、Master CSS 等,你也可以只單獨啟用 UnoCSS - Preset-icons,步驟如下。

Step 1. 安裝套件

npm install -D @unocss/nuxt @unocss/preset-icons @iconify/json

Step 2. 調整配置

在 ./nuxt.config.ts 中的 modules 屬性,添加模組名稱 @unocss/nuxt,我們僅想使用 Preset-icons 所以可以禁用如 unoattributify 等其他選項,僅保持 iconstrue

export default defineNuxtConfig(async () => ({
  modules: [
    ['@unocss/nuxt']
  ],
  unocss: {
    uno: false,
    icons: true,  // 僅啟用 Preset-icons
    attributify: false,
    shortcuts: [],
    rules: []
  }
}))

Step 3. 開始使用

我們於頁面或元件中使用時,可以直接以類別名稱 i- 開頭表示圖示,後面添加接續圖示集 ID 與圖示名稱。

<template>
  <div class="i-fluent-airplane-take-off-24-regular"></div>
</template>

VS Code 插件 - Iconify IntelliSense

當你使用上述這些方式來使用圖示時,使用的圖示集 Iconify,官方也提供了一個 VS Code 插件 Iconify IntelliSense,幫助你在開發上顯示對應的圖示、自動完成圖示名稱、滑入圖示時提示圖示與名稱及程式碼片段等。

https://ithelp.ithome.com.tw/upload/images/20231007/2015261789M89Deb0M.png

Iconify IntelliSense 插件實際效果如下圖:

https://i.imgur.com/RSB6oFU.gif

小結

透過模組來協助網站 Icon 圖示的添加,你可以擁有更好開發體驗,Iconify 圖示集所提供的圖示,如果真的還不夠做使用,你也可以再考慮使用自訂元件的方式來進行載入,相較於傳統的圖片檔,向量圖示能有更靈活的變化與樣式的調整。


感謝大家的閱讀,歡迎大家給予建議與討論,也請各位大大鞭小力一些:)
如果對這個 Nuxt 3 系列感興趣,可以訂閱接收通知,也歡迎分享給喜歡或正在學習 Nuxt 3 的夥伴。

參考資料


上一篇
[Day 21] Nuxt 3 管理網站結構化資料標記 (Structured Data Markup) - SEO 搜尋引擎最佳化系列工具簡介
下一篇
[Day 23] Nuxt 3 多國語系模組 Nuxt I18n 的初入門與基本使用方法
系列文
Nuxt 3 實戰筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言