土法煉鋼的升級之路:Font Awesome 5

前言

Font Awesome 可以說是最熱門的圖示之一,它除了開源外還提供了免費版本,最新的 Font Awesome 5 付費版本就有 1718 個圖示,免費版也有 991 個圖示,因此許多網頁版型都找的到它的蹤跡。
img

由 Google 推出的 Material icons 也是不錯的選擇,只是相對圖示較少。

PrimeNG

PrimeNG 是 Angular 上的知名 UI 元件(Component),我們可以免費使用這些元件,當然您也可以付費購買他們的樣版,非常佛心的它是一次購買終身升級(應該吧),會隨著 Angular 的更新腳步不斷釋出新版本,目前它的圖示是採用 Font Awesome 4,這是便使用它來測試升級到 Font Awesome 5 的結果。

有興趣使用 PrimeNG 的人可以先看看 Angular 線上讀書會:[無主題E10] PrimeNG

首先先利用 Angular CLI 建立一個 Angular 專案,指令如下:
ng new demo-primeng
img

接著我們參照官網 Get Started 說明來加入 PrimeNG,由說明提示 Angular 4 開始多了動畫模組(BrowserAnimationsModule)來協助我們處理 CSS 動畫效果,如果需要可以加入到專案內。
img
開啟 src\app.module.ts,並將 BrowserAnimationsModule 加入到 AppModule 內。
img

現在的 Angular CLI 在建立專案時便會順便幫我們安裝 @angular/animations(忘記從哪一版開始),如果專案沒有的話也可以自己透過 npm install @angular/animations --save 指令來安裝。

接著便要求我們安裝 primengfont-awesome,並載入相關的 CSS 樣式到 .angular-cli.json 內。
img
因為我們要使用 Font Awesome 5,所以先安裝 primeng,指令如下:
npm install --save primeng
img
接著開啟 .angular-cli.json 將說明頁的 css 路徑複製到 styles 內,由於我們未安裝 Font Awesome,因此便省略該連結。
img
我們開起 Font Awesome 首頁下載免費版。
img
將壓縮檔內的資料夾 web-fonts-with-css 複製到專案內的 assets,筆者只保留字型與 css,並將資料夾修改為 font-awesome。
img
接著在首頁(index.html)加入連結。
img

由 Font Awesome 官方文件 JS Component Packages 可以知道從第5版開始套件名稱改變了,免費版本安裝指令如下:
npm install --save @fortawesome/fontawesome-free-webfonts
img

開啟 src\assets\font-awesome\fontawesome-all.css 可以看到 .fas.far.fal.fab 剛好對應到4種字型 solidregularlightbrands(免費版沒有提供 light),原本的 fa 也被保留下來,所以使用 Font Awesome 5 應該是沒有太大的問題。
img

接著我們建立一個 SharedModule(src\app\shared-primeng.module.ts) 來存放與管理 PrimeNG 元件,筆者習慣一開始先將所有元件都匯入,最後階段再將沒有用到的元件給註解且來,避免開發過程中因為漏加元件而出錯。
img

可參考 Angular Material 官方教學 Getting started,或者是 [Angular Material完全攻略] Day 02 - 環境設定 & 安裝 & Hello World

再來將 SharedModule 加入到 AppModule(src\app\app.module.ts) 內,我們便可以開始使用。
img

測試

我們選擇一個元件說明頁面並將範例複製到專案內來測試,筆者選擇 InputGroup,剛好範例也使用到 Font Awesome 圖示。
img
將範例複製到 src\app\app.component.html 內。

app.component.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<h3 class="first">Addons</h3>
<div class="ui-g ui-fluid">
<div class="ui-g-12 ui-md-4">
<div class="ui-inputgroup">
<span class="ui-inputgroup-addon"><i class="fa fa-user"></i></span>
<input type="text" pInputText placeholder="Username">
</div>
</div>

<div class="ui-g-12 ui-md-4">
<div class="ui-inputgroup">
<span class="ui-inputgroup-addon">$</span>
<input type="text" pInputText placeholder="Price">
<span class="ui-inputgroup-addon">.00</span>
</div>
</div>

<div class="ui-g-12 ui-md-4">
<div class="ui-inputgroup">
<span class="ui-inputgroup-addon">www</span>
<input type="text" pInputText placeholder="Website">
</div>
</div>
</div>

我們透過 ng serve 來啟動專案,由瀏覽器觀看圖示也正常顯示,看來一切都沒問題。
img

Dialog

沒問題的話當然就不會浪費這麼多唇舌說這麼多,我們開起 Dialog 說明頁面 將範例複製到專案內。
img
開啟 src\app\app.component.html 並添加 Dialog 元件:

app.component.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<h3 class="first">Addons</h3>
<div class="ui-g ui-fluid">
<div class="ui-g-12 ui-md-4">
<div class="ui-inputgroup">
<span class="ui-inputgroup-addon"><i class="fa fa-user"></i></span>
<input type="text" pInputText placeholder="Username">
</div>
</div>

<div class="ui-g-12 ui-md-4">
<div class="ui-inputgroup">
<span class="ui-inputgroup-addon">$</span>
<input type="text" pInputText placeholder="Price">
<span class="ui-inputgroup-addon">.00</span>
</div>
</div>

<div class="ui-g-12 ui-md-4">
<div class="ui-inputgroup">
<span class="ui-inputgroup-addon">www</span>
<input type="text" pInputText placeholder="Website">
</div>
</div>
</div>

<p-dialog header="Title" [(visible)]="display">
Content
</p-dialog>

<button type="text" (click)="showDialog()" pButton icon="fa-external-link-square" label="Show"></button>

開啟 src\app\app.component.ts 並修改如下:

app.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { Component } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
display = false;
showDialog() {
this.display = true;
}
}

執行 ng serve,並開啟瀏覽器,看起來正常,點選按鈕後會彈出對話是方塊,不過按鈕的圖示(fa-external-link-square)怎麼不見了。
img
連到 Font Awesome 官網 查詢發現 external-link-square 圖示怎麼好像變成付費版才有。
img
再搜尋一下官方資料,從 Upgrading from Version 4 可以發現原來 Font Awesome 5 仍然保留 Font Awesome 4 的圖示,只是名稱改變了。
img
開啟 src\app\app.component.html 並將圖示名稱fa-external-link-square 改成 fa-external-link-square-alt,重新執行後就發現圖示出現了。

app.component.html
1
2
3
4
5
6
7
...
<p-dialog header="Title" [(visible)]="display">
Content
</p-dialog>

<button type="text" (click)="showDialog()" pButton icon="fa-external-link-square-alt" label="Show"></button>

img

Close

從官方範例來看 Dialog 元件再標題列的右方還提供關閉按鈕,這還是蠻實用的功能,當然我們也可以自己在下方手動加入按鈕。
img
從官方文件可以看到我們可以透過 closable 屬性來設定,但是預設值已經是 true,照理說應該會出現才對,難道是預設值變成 false 而文件未更新。
img
開啟 src\app\app.component.html 並添加 closable 屬性。

app.component.html
1
2
3
4
5
...
<p-dialog header="Title" [(visible)]="display" [closable]="true">
Content
</p-dialog>
...

開啟網頁發現仍然沒有出現關閉按鈕。
img
直接查看官方範例按鈕的內容,可以看到它是採用 fa-close 圖示。
img
查看 Upgrading from Version 4 可以發現 close 被改成 times,而且既使付費版也沒有同名圖示。
img
img
問題來了,Dialog 元件並沒有提供修改圖示功能,難不成要降回 Font Awesome 4,或者同時載入 4、5,亦或修改原始碼。

官方提供的 Version 4 Shim (SVG with JavaScript only) 的升級模式,對於採用圖示字型(web-fonts-with-css)的樣版有可能會出現跑版問題。

其實既然既然 Font Awesome 5 也有涵蓋 Font Awesome 4 的圖示,那我們所缺少的就是相關的 CSS 選擇器設定,我們開起 src\assets\font-awesome\css\fontawesome-all.css,搜尋 fa-times 便可以查出該選擇器。
img
接著我們建立一個 fontawesome-support-v4.css,將 fa-times 選擇器複製到檔案內並將名稱改回 Font Awesome 4 的 fa-close
img
接著我們在 index.html 加入連結。
img
開啟瀏覽器可以看到關閉按鈕圖示已經出現了。
img

修仙之路

既然結果可行,就索性把剩下的選擇器都給補上。
img
接著我們把 src\app\app.component.html 恢復回官方範例。
img
開啟瀏覽器可以發現一切正常。
img

[**fontawesome-support-v4.css**](/uploads/fontawesome-support-v4.css)

fontawesome-support-v4.min.css