Angular Material 18+ 高级教程 – Custom Themes for Material Design 3 (自定义主题 Material 3)

v18 更新重要说明

从 Angular Material v18 开始,默认使用的是 Material 3 Design (简称 M3)。

而且是正式版,不再是 experimental preview 了。

由于本篇写的时候是 v17,而我现在没力修改下面的 demo 代码,所以这里 highlight 一下 breaking changes 就好:

  1. 不需要 @angular/material-experimental 

    @use '@angular/material-experimental' as matx; 

    直接用 @angular/material 即可

    @use '@angular/material' as mat;
  2. 不需要 m3 prefix 了,比如

    matx.$m3-blue-palette
    换成
    mat.$blue-palette
  3. 如果是用 m2 版本,反而要加上 prefix m2

    mat.define-dark-theme
    换成
    mat.m2-define-dark-theme

     

前言

续上一篇的 Custom Themes for Material Design 2 (简称 M2) 之后,我们继续看 Material Design 3 (简称 M3)。(提醒:没有看过 M2 的朋友请先看 M2 的哦)

Angular Material v17.2.0 发布了对 Material Design 3 的实现 (preview 版本)。

M2 和 M3 主要只是样式不同而已,组件的交互,使用接口等等全部都一样,所以你也可以把它理解为只是换了一个默认主题 (Theme)。

 

参考

Angular Material Docs – Material 3 Theming

Material Design Docs – Color System

Material Design Docs – Typography

 

Angular Material Design 3 Get Started

首先添加 Angular Material 

ng add @angular/material

选择 Custom Theme

添加 @angular/material-experimental 包

yarn add @angular/material-experimental

App Template

<mat-card>
  <mat-card-header>
    <mat-card-title>Title</mat-card-title>
    <mat-card-subtitle>Subtitle</mat-card-subtitle>
  </mat-card-header>
  <mat-card-content>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium, iusto?</p>
    <div class="button-list">
      <button mat-raised-button color="primary">Primary</button>
      <button mat-raised-button color="accent">Accent</button>
      <button mat-raised-button color="warn">Warn</button>
    </div>
  </mat-card-content>
</mat-card>

App Styles (美化一下而已)

mat-card {
  max-width: 360px;

  mat-card-content {
    padding: 16px;

    .button-list {
      margin-top: 16px;
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 16px;
    }
  }
}
View Code

styles.scss (先来个 M2 版本)

@use '@angular/material' as mat;

@include mat.core();

$m2-primary: mat.define-palette(mat.$indigo-palette);
$m2-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$m2-warn: mat.define-palette(mat.$red-palette);

$m2-typography: mat.define-typography-config();
$m2-theme: mat.define-light-theme((
  color: (
    primary: $m2-primary,
    accent: $m2-accent,
    warn: $m2-warn,
  ),
  typography: $m2-typography
));
@include mat.all-component-themes($m2-theme);
View Code

效果

styles.scss (M3 版本)

@use '@angular/material' as mat;
@use '@angular/material-experimental' as matx;

@include mat.core();

$m3-theme: matx.define-theme((
  color: (
    theme-type: light,
    primary: matx.$m3-blue-palette,
    tertiary: matx.$m3-red-palette,
  ),
  typography: (
    plain-family: 'Roboto',
    brand-family: 'Roboto',
    bold-weight: 700,
    medium-weight: 500,
    regular-weight: 400
  ),
  density: (
    scale: 0
  )
));

html {
  @include mat.all-component-themes($m3-theme);
}

效果

M2 和 M3 的风格差别挺大的,圆角更明显了,颜色运用不太一样,字体尺寸也有微调。

不过这些我都不关心,毕竟我不是设计师,看不出哪一个比较好。

 

对比 Material 2 和 Material 3

首先是 M3 需要引入多一个包 @angular/material-experimental

@use '@angular/material' as mat;
@use '@angular/material-experimental' as matx;

当然,它依然需要 @angular/material 包,因为 M3 并不是一个全新的 Material Design 实现,它只是一个新主题而已。

Define Color Theme

$m3-color-theme: matx.define-theme((
  color: (
    theme-type: light,
    primary: matx.$m3-blue-palette,
    tertiary: matx.$m3-green-palette,
  )
));

M3 和 M2 有几个区别:

  1. M2 有 define-light-theme 和 define-dark-theme 两个方法。

    而 M3 只有一个 define-theme 方法,取而代之的是它的 color 参数有一个 theme-type 属性用来表达是 light theme or dark theme。

  2. M2 可以配置 primary, accent, warn 三个颜色

    M3 只可以配置 primary 和 tertiary 两个颜色

    这个 tertiary 相等于 M2 的 accent,而 M2 的 warn 在 M3 叫 error。

  3. M3 目前不支持 Custom Base Palette (M2 支持),我们只能选择几个固定的颜色

Define Typography Theme

$m3-typography-theme: matx.define-theme((
  typography: (
    brand-family: 'Roboto',
    plain-family: 'Roboto',
    bold-weight: 700,
    medium-weight: 500,
    regular-weight: 400
  ),
));

M3 和 M2 有几个区别:

  1. M3 不允许调整 Type Scale Level

  2. M3 只允许调整 5 个属性

    brand-family 用于 headline

    plain-family 用于 paragraph

    regular, medium, bold 用于 font-weight

  3. M3 的 Type Scale Level 有新的命名和尺寸

    它分 5 个大 Level:Display,Headline,Title,Body,Label

    大 Level 里又分小 Level:Large,Medium,Small

Define Density Theme

$m3-density-theme: matx.define-theme((
  density: (
    scale: 0
  )
));

scale 最大是 0,最小是 -3

Apply Theme to Components

M3 apply theme 的方式和 M2 大同小异。

html {
  @include mat.all-component-bases($m3-theme); 
}

唯一的区别是 M3 一定要 under 某个 selector。通常放 html {} 或者 :root 都可以。

mat.all-component-bases 输出的是 CSS Variables,这点 M2 和 M3 都是一样的。

apply theme 1 by 1:

html {
  @include mat.all-component-bases($m3-base-theme);
  @include mat.all-component-colors($m3-color-theme);
  @include mat.all-component-typographies($m3-typography-theme);
  @include mat.all-component-densities($m3-density-theme);
}

apply components 1 by 1:

html {
  @include mat.button-base($m3-base-theme);
  @include mat.button-color($m3-color-theme);
  @include mat.button-typography($m3-typography-theme);
  @include mat.button-density($m3-density-theme);
}

眼尖的朋友或许会发现到 color 属性失灵了

<button mat-raised-button color="primary">Primary</button>
<button mat-raised-button color="accent">Accent</button>
<button mat-raised-button color="warn">Warn</button>

三个 Button 的颜色都是 primary。

<button mat-raised-button color="tertiary">Accent</button>
<button mat-raised-button color="error">Error</button>

即便换成最新的命名效果也是一样。

这是因为,M3 不再自动输出相关代码。

我们看看 M2

@include mat.button-color($m2-theme);

M2 会自动输出下面这几段

M3 则不会了。

解决方法有 2 个:

  1. 自己补上

    html {
      .mat-mdc-raised-button.mat-tertiary {
        @include mat.button-color($m3-color-theme, $color-variant: tertiary);
      }
      .mat-mdc-raised-button.mat-error {
        @include mat.button-color($m3-color-theme, $color-variant: error);
      }
    }

    <button color="tertiary"> Angular Material 会自动添加 class mat-tertiary

  2. 使用向后兼容方法

    html {
      @include matx.color-variants-back-compat($theme);
    }

    color-variants-back-compat 是 Angular Material 特别为了方便向后兼容而设的。

    它的源码在 _color-api-back-compat.scss

    最终也是使用了 @include mat.button-color($m3-color-theme, $color-variant: tertiary)

     

Custom component reads theme information

M2 和 M3 大同小异,方法是同一个,只是参数有些换了而已。

依然是使用 mat.get-theme-color 方法,但是参数不一样。

它有两种调用方式:

Reading tonal palette colors

第一种调用方式是传入 3 个参数,这个叫 Reading tonal palette colors。

参数一是 $m3-theme

参数二是 Palette Name,选项有:

  1. primary
  2. secondary
  3. tertiary
  4. error
  5. neutral
  6. neutral-variant

参数三是明度 Level,选项有:

  1. 0
  2. 10
  3. 20
  4. 30
  5. 40
  6. 50
  7. 60
  8. 70
  9. 80
  10. 90
  11. 95
  12. 99
  13. 100

Reading color roles

第二种调用方式是传入 2 个参数,这个叫 Reading color roles。

参数一是 $m3-theme

参数二是 Role Name:

  • primary
  • on-primary
  • primary-container
  • on-primary-container
  • primary-fixed
  • primary-fixed-dim
  • on-primary-fixed
  • on-primary-fixed-variant
  • secondary
  • on-secondary
  • secondary-container
  • on-secondary-container
  • secondary-fixed
  • secondary-fixed-dim
  • on-secondary-fixed
  • on-secondary-fixed-variant
  • tertiary
  • on-tertiary
  • tertiary-container
  • on-tertiary-container
  • tertiary-fixed
  • tertiary-fixed-dim
  • on-tertiary-fixed
  • on-tertiary-fixed-variant
  • error
  • on-error
  • error-container
  • on-error-container
  • surface-dim
  • surface
  • surface-bright
  • surface-container-lowest
  • surface-container-low
  • surface-container
  • surface-container-high
  • surface-container-highest
  • on-surface
  • on-surface-variant
  • outline
  • outline-variant
  • inverse-surface
  • inverse-on-surface
  • inverse-primary
  • scrim
  • shadow

想多了解 Color Roles 可以看这篇 Docs – Color roles

举个例子,我们设定的 primary color 被用于 Container (通常指 background-color) 时,它的颜色并不是 primary 而是会浅一点。

On Primary Container 的 On 指的是 On Top,也就是 bg-color 和 color 的 contrast 关系。

M3 的颜色用法和 M2 不太一样,M2 我们会拿 primary default,primary lighter,而 M3 我们不太会拿 primary 50,取而代之的是直接拿 primary-container。

另外,M2 可以拿组件 (e.g. dialog, button) 的 foreground 和 background,M3 则不行。

Apply alpha to color

mat.get-theme-color 方法返回的是 HEX (hexadecimal),如果想加入 alpha 可以利用 alpha hexadecimal (#RRGGBBAA)。

background-color: #{mat.get-theme-color($m3-color-theme, primary)} + '09';
--background-color: #{mat.get-theme-color($m3-color-theme, primary)}09;

如果想更灵活可以把 hex 转换成 hsl (提醒:转换后颜色可能会有微差哦)

$color: mat.get-theme-color($m3-color-theme, primary);
$hue: color.hue($color);
$saturation: color.saturation($color);
$lightness: color.lightness($color);

app-root {
  --primary-hsl-value: #{$hue} #{$saturation} #{$lightness};
  background-color: hsl(var(--primary-hsl-value) / 50%);
}

和 M2 一样使用 mat.get-theme-typography 方法,参数也一样,只是 Scale Level Name 换了。

M3 Scale Level Name:

  • display-large
  • display-medium
  • display-small
  • headline-large
  • headline-medium
  • headline-small
  • title-large
  • title-medium
  • title-small
  • body-large
  • body-medium
  • body-small
  • label-large
  • label-medium
  • label-small

和 M2 一摸一样,这里就不复述了。

 

总结

1. M3 是建立在 M2 基础上的,所以必须先掌握 M2

2. M3 主要是改了 Styles (CSS) 的部分,组件交互 (TS) 的部分完全没有变动。

2. M3 的颜色运用和 M2 区别比较大,这个是 Material Design 的知识,多参考 Material Design 3 Color System

3. M3 的 Typography 不能自定义 Type Scale Level 尺寸了,而且 Type Scale Level Name 都换了。

4. M3 目前是 preview 版本,不过相信 Angular Material v18 就会变成稳定版了,因为它也不算是大改。

M3 给我的感觉是限制更多了,能自定义的地方更少了。

 

 

目录

上一篇 Angular Material 18+ 高级教程 – Custom Themes for Material Design 2 (自定义主题 Material 2)

下一篇 Angular Material 18+ 高级教程 – CDK Portal

想查看目录,请移步 Angular 18+ 高级教程 – 目录

喜欢请点推荐👍,若发现教程内容以新版脱节请评论通知我。happy coding 😊💻

 

posted @ 2024-02-22 21:20  兴杰  阅读(609)  评论(1编辑  收藏  举报