DAY10 — 切換不同的佈景主題

Jason Z
jason-read-code
Published in
Feb 16, 2022

在前幾篇,挑選一套自己喜歡的UI框架中提到,挑選Nebular的其中一個重要的原因是:可以很方便快速切換主題。這一篇就要來示範,如何做到一件切換主題!

什麼是切換佈景主題

自從暗黑模式流行起來之後,越來越多的網站與應用程式加入了即時切換不同佈景主題的模式。一般來說,都是光亮模式與暗黑模式之間的切換。

而Nebular 提供六套不同的預設主題,供開發者直接套用。我們就來挑戰,切換 Light 與 Dark 兩種不同的主題吧!

切換佈景主題的原理也很簡單,也就是切換不同主題的CSS檔案,讀取CSS佈景主題的變數之後,套用上去,達到切換佈景主題的效果

在執行時,即時切換主題

在Nebular的文件 Change Current Theme 的章節介紹到,如何在執行的時候切換佈景主題:

// ...
constructor(private themeService: NbThemeService) {
this.themeService.changeTheme('corporate');
}

就這樣,沒了!就是這麼簡單!

只要引入Nebular 的 NbThemeService ,並且呼叫 changeTheme 的方法,就可以即時切換主題。

這個就是Nebular吸引我的地方,相較其他的UI 框架切換主題麻煩的設定,Nebular 簡潔俐落多了。

在此同時也要反思自己,有沒有辦法寫出這麼簡潔又好用的程式碼呢?

製做切換主題的按鈕

了解如何切換主題後,要製做一個按鈕,讓使用者點擊切換佈景主題。

在頁面的右上角,有一個切換的按鈕讓使用者切換佈景主題

暗黑模式

亮白模式

製做按鈕

按鈕和 icon 是利用 nebular 內建的元件製做的,使用方法很簡單,只要引入相關模組,就可以使用,另外還要匯入 FormsModule 使用雙向綁定來記錄元件的狀態

@NgModule({
imports: [
NbToggleModule,
NbIconModule,
FormsModule
]
})

再來寫下html

<nb-toggle
status="basic"
[(ngModel)]="themeToggle"
(ngModelChange)="changeThemeMode(themeToggle)"
>
<nb-icon [icon]="themeToggle ? 'moon' : 'sun-outline'"></nb-icon>
</nb-toggle>

利用 ngModel 去紀錄目前按鈕的狀態,再來用 ngModelChange 去監聽,當綁定的值出現變化,便觸發 changeThemeMode 的方法去切換佈景主題。

另外icon也利用 themeToggle 的變數去控制目前要顯示太陽或月亮表示當前的佈景主題

最後來寫邏輯 typescript

themeToggle = true;
constructor(private themeService: NbThemeService) {
this.detectTheme();
}
changeThemeMode(themeToggle: boolean): void {
const theme = themeToggle ? 'dark' : 'default';
this.themeService.changeTheme(theme);
}
detectTheme(): void {
const isDarkMode =
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches;
this.themeToggle = isDarkMode;
this.changeThemeMode(this.themeToggle);
}

也就是依照官網的寫法,來切換主題。

但是在這裡有一個特別的是,筆者寫了一個 detectTheme 的方法去偵測使用者裝置系統預設主題,如果使用者裝置設定暗黑模式,那麼網站打開預設就會是暗黑模式,讓使用者可以有更一致的使用者體驗。

window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; 就是一個很好的判斷方法

如此一來就大功告成囉,最後來看看成果吧!

--

--

Jason Z
jason-read-code

哲學系畢業的前端工程師,大部分時間都在搞鐵路系統,喜歡寫程式外,更喜歡鐵道,欣賞路上每個平凡的風景