如何實現Angular Material自定義主題

什麼是主題

主題就是一組要應用於 Angular Material 的顏色,也能夠理解成應用的皮膚。在之前使用 QQ 空間的時候,騰訊就作好多些空間皮膚(主題)進行出售。如今 Android 手機系統也都有好多主題,讓用戶本身手機系統的主題。css

在 Angular Material 中,主題由多個調色板組成。具體來講,包括:html

  • 主調色板:那些在全部屏幕和組件中普遍使用的顏色。
  • 強調調色板:那些用於浮動按鈕和可交互元素的顏色。
  • 警告調色板:那些用於傳達出錯狀態的顏色。
  • 前景調色板:那些用於問題和圖標的顏色。
  • 背景色調色板:那些用作原色背景色的顏色。

預約義主題

Angular Material 自帶了幾個預構建主題的 css 文件。這些主題文件包含了全部核心樣式(全部組件中通用的),這樣你的應用就只須要包含單個 css 文件了。node

有效的預約義主題有:typescript

  • deeppurple-amber.css
  • indigo-pink.css
  • pink-bluegrey.css
  • purple-green.css

你能夠從 @angular/material/prebuilt-themes 直接把主題文件包含到應用中。json

若是你正在使用 Angular CLI,那麼只須要在 styles.css 文件中添加一行就能夠了:數據結構

@import '@angular/material/prebuilt-themes/deeppurple-amber.css';
複製代碼

若是你使用的 ng add @angular/material 添加的依賴,Material Schematics 會在控制檯給出交互信息,在選擇相應的主題後,會自動將樣式添加到 angular.json 中:app

"styles": [
              "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
              "src/styles.scss"
   ],
複製代碼

自定義主題

自定義主題文件要作兩件事:函數

  1. 導入 mat-core() 混入器。它包括全部功能多個組件使用的公共樣式。**在你的應用中,應該只包含一次該混入器。**若是包含屢次,你的應用就會出現這些公共樣式的多個副本。
  2. 定義一個主題數據結構,它由多個調色板組成。該對象能夠用 mat-light-thememat-dark-theme 函數構建。而後,函數的輸出會傳給 angular-material-theme 混入器,它會輸出全部該主題所對應的樣式。

典型的主題文件定義以下:ui

// 引入material的theming,其中包含了混入器
@import '~@angular/material/theming';

// 導入核心混入器,確保只導入一次
@include mat-core();

// 定義主調色板
$candy-app-primary: mat-palette($mat-indigo);

// 強調調色板
$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);

// 警告調色板
$candy-app-warn:    mat-palette($mat-red);

// 建立一個light主題
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);

// 啓動主題
@include angular-material-theme($candy-app-theme);
複製代碼

多重主題

你能夠經過屢次調用 angular-material-theme 混入器,每次包含一些額外的 CSS 類,來爲應用建立多個主題。this

記住,只能包含 @mat-core 一次;不該該讓每一個主題都包含它一次。

多重主題的例子:

// 引入material的theming,其中包含了混入器
@import '~@angular/material/theming';
// Plus imports for other components in your app.

// 導入核心混入器,確保只導入一次
@include mat-core();

// 定義主調色板
$candy-app-primary: mat-palette($mat-indigo);
// 強調調色板
$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);
// 建立一個light主題
$candy-app-theme:   mat-light-theme($candy-app-primary, $candy-app-accent);

// 將candy-app-theme定義成默認主題
@include angular-material-theme($candy-app-theme);


// 定義個深色主題.
$dark-primary: mat-palette($mat-blue-grey);
$dark-accent:  mat-palette($mat-amber, A200, A100, A400);
$dark-warn:    mat-palette($mat-deep-orange);
$dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

// 全部在unicorn-dark-theme樣式下的組件主題都將是深色的
.unicorn-dark-theme {
  @include angular-material-theme($dark-theme);
}
複製代碼

基於浮層的組件

因爲某些組件(好比菜單、選擇框、對話框等)位於全局的浮層容器中,因此想要讓它們被主題的 css 類選擇器(好比 .unicorn-dark-theme)影響到還須要作一個額外的步驟。

要作到這一點,你能夠給全局浮層容器添加一個合適的類。好比上面的例子要改爲這樣:

import {OverlayContainer} from '@angular/cdk/overlay';

@NgModule({
  // ...
})
export class UnicornCandyAppModule {
  constructor(overlayContainer: OverlayContainer) {
    overlayContainer.getContainerElement().classList.add('unicorn-dark-theme');
  }
}
複製代碼

固然,浮層容器也是渲染在 body 中的,因此能夠在 body 中添加樣式

<body class="unicorn-dark-theme">
    <!--....-->
</body>
複製代碼

這樣就不須要上面的 ts 類了。

主題動態切換

在上面多主題的基礎上,咱們實現主題的動態切換。能夠經過修改 body 的 class,從而實現主題的切換。

export class AppComponent {
  constructor(@Inject(DOCUMENT) private document: Document) {}

  changeTheme() {
    const theme = 'unicorn-dark-theme';
    this.document.body.classList.toggle(theme);
  }
}
複製代碼
相關文章
相關標籤/搜索