如何理解组件的 angular material 主题中使用的颜色?

How to understand what colors are being used in angular material theme for the components?

我们在项目 https://material.angular.io/. It allows to define custom color theme https://material.angular.io/guide/theming 上使用 angular-material。我们还有一位设计师想要用正确的颜色绘制 UI 套件(例如,不同状态的输入)。可以通过 angular-material 定义的调色板看起来像蓝色原色的调色板:

$my-accent: (
  50 : #e1f2fb,
  100 : #b4dff6,
  200 : #83caf0,
  300 : #51b4ea,
  400 : #2ba4e6,
  500 : #0694e1,
  600 : #058cdd,
  700 : #0481d9,
  800 : #0377d5,
  900 : #0265cd,
  A100 : #f5f9ff,
  A200 : #c2dcff,
  A400 : #8fbfff,
  A700 : #75b0ff,
  contrast: (
    50 : #000000,
    100 : #000000,
    200 : #000000,
    300 : #000000,
    400 : #000000,
    500 : #ffffff,
    600 : #ffffff,
    700 : #ffffff,
    800 : #ffffff,
    900 : #ffffff,
    A100 : #000000,
    A200 : #000000,
    A400 : #000000,
    A700 : #000000,
  )
);

但是,如果我们查看他们网站上的标签

不清楚上面调色板中的哪些颜色用于下划线、文本、用户单击选项卡时的效果等。

是否有可能以某种方式创建具有正确颜色的 UI 套件?或者我们必须调试 html 来映射与定义的调色板一起使用的颜色?可能我们应该尝试全局覆盖所有颜色,但这看起来很难且耗时。

在这个答案的最后,我展示了源代码来准确地找到调色板中使用了哪些色调,但你真的不需要担心它。

您可以选择将三个主题中的哪一个与组件的 color 属性 一起使用,这实际上是您唯一应该做出的决定。组件设计人员将准确选择适合组件的哪一部分的色调。他们希望您设计整个主题来覆盖颜色的原因是组件的所有部分都具有相同的相对色调,他们不希望您只覆盖组件的一部分。

您链接的指南 (https://material.angular.io/guide/theming) 描述了如何在特定范围内覆盖整个项目或单个组件的主题:

You can use Angular Material's Sass mixins to customize component styles within a specific scope in your application. The CSS rule declaration in which you include a Sass mixin determines its scope. The example below shows how to customize the color of all buttons inside elements marked with the .my-special-section CSS class.

@use '@angular/material' as mat;
.my-special-section {  $special-primary:
mat.define-palette(mat.$orange-palette);  $special-accent:
mat.define-palette(mat.$brown-palette);  $special-theme:
mat.define-dark-theme((    color: (primary: $special-primary, accent:
$special-accent),  ));

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

我对源代码做了一些挖掘,并在此处找到了定义调色板的函数:https://github.com/angular/components/blob/master/src/material/core/theming/_theming.scss

可以看到默认值为500,浅色为100,深色为700

/// Creates a map of hues to colors for a theme. This is used to define a theme palette in terms
/// of the Material Design hues.
/// @param {Map} $base-palette Map of hue keys to color values for the basis for this palette.
/// @param {String | Number} $default Default hue for this palette.
/// @param {String | Number} $lighter "lighter" hue for this palette.
/// @param {String | Number} $darker "darker" hue for this palette.
/// @param {String | Number} $text "text" hue for this palette.
/// @returns {Map} A complete Angular Material theming palette.

@function define-palette($base-palette, $default: 500, $lighter: 100, $darker: 700,
  $text: $default) {
  $result: map.merge($base-palette, (
    default: _get-color-from-palette($base-palette, $default),
    lighter: _get-color-from-palette($base-palette, $lighter),
    darker: _get-color-from-palette($base-palette, $darker),
    text: _get-color-from-palette($base-palette, $text),

    default-contrast: get-contrast-color-from-palette($base-palette, $default),
    lighter-contrast: get-contrast-color-from-palette($base-palette, $lighter),
    darker-contrast: get-contrast-color-from-palette($base-palette, $darker)
  ));

  // For each hue in the palette, add a "-contrast" color to the map.
  @each $hue, $color in $base-palette {
    $result: map.merge($result, (
      '#{$hue}-contrast': get-contrast-color-from-palette($base-palette, $hue)
    ));
  }

  @return $result;
}

他们通常会使用此功能将颜色导入组件:

/// Gets a color from a theme palette (the output of mat-palette).
/// The hue can be one of the standard values (500, A400, etc.), one of the three preconfigured
/// hues (default, lighter, darker), or any of the aforementioned prefixed with "-contrast".
///
/// @param {Map} $palette The palette from which to extract a color.
/// @param {String | Number} $hue The hue from the palette to use. If this is a value between 0
//     and 1, it will be treated as opacity.
/// @param {Number} $opacity The alpha channel value for the color.
/// @returns {Color} The color for the given palette, hue, and opacity.

@function get-color-from-palette($palette, $hue: default, $opacity: null) {
  // If hueKey is a number between zero and one, then it actually contains an
  // opacity value, so recall this function with the default hue and that given opacity.
  @if meta.type-of($hue) == number and $hue >= 0 and $hue <= 1 {
    @return get-color-from-palette($palette, default, $hue);
  }

  // We cast the $hue to a string, because some hues starting with a number, like `700-contrast`,
  // might be inferred as numbers by Sass. Casting them to string fixes the map lookup.
  $color: if(map.has-key($palette, $hue), map.get($palette, $hue), map.get($palette, $hue + ''));

  @if (meta.type-of($color) != color) {
    // If the $color resolved to something different from a color (e.g. a CSS variable),
    // we can't apply the opacity anyway so we return the value as is, otherwise Sass can
    // throw an error or output something invalid.
    @return $color;
  }

  @return rgba($color, if($opacity == null, opacity($color), $opacity));
}

例如这里导入了高亮标签的颜色:https://github.com/angular/components/blob/master/src/material/tabs/_tabs-theme.scss

.mat-tab-group, .mat-tab-nav-bar {
    $theme-colors: (
      primary: $primary,
      accent: $accent,
      warn: $warn
    );

    @each $name, $color in $theme-colors {
      // Set the foreground color of the tabs
      &.mat-#{$name} {
        @include _label-focus-color($color);
        @include _ink-bar-color($color);

        // Override ink bar when background color is the same
        &.mat-background-#{$name} {
          > .mat-tab-header, > .mat-tab-link-container {
            @include _ink-bar-color($color, default-contrast);
          }
        }
      }
    }

@mixin _ink-bar-color($color, $hue: default) {
  .mat-ink-bar {
    background-color: theming.get-color-from-palette($color, $hue);
  }
}

因此墨栏将是主题(primaryaccentwarn)的默认(500)颜色。