關於 SVG Icon

在開始之前,首先聊聊 SVG 的格式。

其實 SVG Icon 是由一個個 <path> 所組成的字串,而這些 <path> 的值其實可以取出來,再重新組合成一個完整的字串,最後這個字串所呈現的結果也會與原先的 SVG Icon 相同。

Svg icon format

圖片來源為 Quasar Framework 官方在 QIcon 的文檔裡面,對於 Svg icon format 的說明。

官方提供的 SVG 用法

Image icons

使用 Quasar 官方提供的 Image icons 方法,就可以在 QBtn 與 QIcon 上使用我們的 SVG Icon 了。

不過 Image icons 有個缺點就是無法更改顏色,像是我們常會針對 Hover 與 Active 等狀態,去定義不同的 Icon 顏色,然而使用 Image icons 這種方式的話,我們就無法更改顏色哩。

Image icons

如果使用這個方法,可以把 SVG Icons 放在 /src/statics 資料夾下,這樣在寫檔案路徑時比較方便

Inlined svg

Quasar 在 v1.7 版本之後,新增了叫做 Inlined svg 的使用方法。

我們可以直接在 <q-icon> 裡面把 SVG 的原始內容複製貼上,基本上格式就如下圖所示,可以放 <path> 以及其他 SVG 會出現的標籤,像是 <circle> 或是 <rect> 等標籤。

Inlined svg

不過在 <svg> 標籤裡面不能放 <style> 這個標籤,如果你的 SVG Icon 有使用 <style> 標籤定義樣式的話,要額外改寫到 <path> 上才行。

上圖第三行就是在 <path> 加上 fill="none" 來定義 Icon 的預設顏色,所以如果要預先填入白色的話,就是在後面寫 fill="#fff" 就可以哩。

基本上官方提供的這個 Inlined svg 是可以使用的,操作很簡單,基本的屬性也都能直接定義。
不過有個缺點就是 Vue 元件會出現 SVG 的原始碼,有些圖片的 <path> 長度很長,甚至有很多個 <path>,這時候程式碼就會顯得比較雜亂。

改良寫法

方法一:使用 QIcon 搭配 v-html

這是基於 Quasar 官方寫法 (Inlined svg) 的延伸版本,會想到這個寫法,是因為 SVG Icon 的原始碼通常都很長一串,如果我們的專案有使用 ESLint 來規範程式碼,就會出現因為 <path> 字數太多而跳錯的問題。

要解決這個問題,我們可以將 SVG Icon 儲存成一個 JS 檔案,等到要使用的時候再透過 v-html 把這個檔案塞進 <q-icon> 裡面就可以了。

// src/path/to/exampleSvg.js
export default '<svg xmlns="..." viewBox="0 0 30 30"><circle cx="15" cy="15" r="15"/><path class="a" d="M21.113,22.9H11.506a1"/></svg>';

接下來我們還不能直接使用 v-html,在那之前我們需要先把 JS 檔案 import 進來,並且做一個初始化的動作,這樣後續使用時才能吃到內容。

import exampleSvg from '../path/to/exampleSvg.js';

export default {
  name: 'exampleCard',
  created() {
    this.exampleSvg = exampleSvg;
  },
};

都完成之後,就能使用 v-html 插入 Icon 囉!

<q-icon v-html="exampleSvg" size="30px" color="primary" />

重點補充說明:

  • 外框可再加上 v-ripple:white 來模擬 QBtn 的點擊效果
  • 可直接調整 size 與 color,不需要使用到 /deep/
  • QIcon 內部字體的顏色 (fill) 需使用 .deep-icon /deep/ .a 來指定調整

方法二:使用 QBtn 搭配 /deep/

上面的延伸寫法是 QIcon 使用的,但是 Quasar 裡面其實還有很多 Components 都會使用到 Icon,像是 QBtn 就是最常見的案例,因此方法二會介紹以常規方式使用 Quasar 元件時,該怎麼使用自己的 SVG Icon。

Step 1:將 SVG Icon 全部轉成字串

如何將 SVG Icon 轉為字串格式:

  • <path> 裡面 d="..." 的內容全部擷取出來,組合成一個新的字串
  • 如果 Icon 由多個 <path> 組成,可以用一個空格區分不同的 <path> 的內容
  • viewBox 加在字串的最後方,以一個 | 符號與前面的內容分隔開。

最後製作出來的結果就會是一個字串格式,我們將這個字串匯出,並儲存為一個 JS 檔案。

export default 'M20.142,.....,27.165Z|0 0 30 30';

Step 2:透過 v-bind 使用

接下來一樣要先做 import 與初始化(與方法一相同)的動作,才能在 <q-btn> 上使用剛才做好的字串 Icon。

我們可以透過 v-bind:icon 的方式把我們的 Icon 綁上去,並且使用 @click:color 的三元運算,來完成模擬 Qbtn 的點擊效果。

例如:

<q-btn
  round
  flat
  :icon="exampleSvg"
  @click="isThumbUp = !isThumbUp"
  :color="isThumbUp? 'primary': 'grey'"
  size="14px"
></q-btn>

重點補充說明:

  • 可使用 CSS /deep/ 來調整按鈕的字體大小 (.q-icon) 與寬高 (.q-btn__wrapper)
  • 透過 @click:color 切換按鈕顏色(三元條件運算子)

參考資料

  1. javascript - Icon in Quasar Button Component does not change size - Stack Overflow

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫