为其他元素

时间:2017-10-15 21:45:13

标签: css angular themes angular-material

我正在构建一个应用程序,但我希望保持一致的颜色方案,可以通过设置进行更改,因此我使用带有角度(2+)的材质(2),但我不知道如何在元素上获得颜色方案不直接提供使用color="primary"为它们着色的能力,所以我试着弄清楚如何获得我的Material 2主题使用的颜色/颜色方案。 我希望它在主题更改时更改,例如我的导航栏将适应主题更改,因为它设置为

<mat-toolbar color="primary" class="fixed-navbar mat-elevation-z10">

但是材质2中的网格元素并没有采用相同的参数,所以我试图用足够接近的颜色来设置它的颜色,或者根本不匹配它(它不会调整到主题变化),如下所示:

enter image description here

我希望它与主题垫匹配颜色,这是在这里(并在导航栏设置中选择的选项上更改)

@import '~@angular/material/theming';

@include mat-core();



$candy-app-primary: mat-palette($mat-red);
$candy-app-accent:  mat-palette($mat-deep-orange, A200, A100, A400);
$candy-app-warn:    mat-palette($mat-red);
$candy-app-theme: mat-dark-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);

// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
.default {
  @include angular-material-theme($candy-app-theme);
}
.light {
  $light-primary: mat-palette($mat-blue, 200,300, 900);
  $light-accent:  mat-palette($mat-light-blue, 600, 100, 800);
  $light-warn:    mat-palette($mat-red, 600);
  $light-theme: mat-dark-theme($light-primary, $light-accent, $light-warn);
  @include angular-material-theme($light-theme);
}
@include angular-material-theme($candy-app-theme);

6 个答案:

答案 0 :(得分:26)

我找到了一个很棒的解决方法!!!! 我很高兴能够展示这一点,因为它一直困扰着我如何实现这一目标。 所以这里; 首先,将所有css文件更改为scss;

适用于现有项目

  •   

    在控制台ng set defaults.styleExt=scss

    中运行
  • 将所有现有.css个文件重命名为.scss

  • 手动将styles.angular-cli.json的文件扩展名从.css更改为.scss
  • 如果您没有使用像WebStorm Refactor这样的工具重命名,那么请手动将所有styleUrls.css更改为.scss

对于未来的项目

  • 仅为您的新项目使用ng new your-project-name --style=scss

  • 对于使用scss的所有新项目,请使用ng set defaults.styleExt=scss --global

现在您需要在app根目录中拥有一个theme.scss文件,如下所示: where themes are

现在在你的style.scss文件中你要添加以下内容(你可以看到我推荐的背景颜色,但你可以将它更改为任何元素,以便你想要的网站主题):

编辑:您不需要将此自定义@mixin元素放在styles.scss中,您可以将其放入*name*.component.scss中的任何一个,然后只需导入并包含它与给出示例的方式相同!

@import '~@angular/material/theming';

// Define a custom mixin that takes in the current theme
@mixin theme-color-grabber($theme) {
  // Parse the theme and create variables for each color in the pallete
  $primary: map-get($theme, primary);
  $accent: map-get($theme, accent);
  $warn: map-get($theme, warn);
  // Create theme specfic styles
  .primaryColorBG {
    background-color: mat-color($primary);
  }
  .accentColorBG {
    background-color: mat-color($accent);
  }
  .warnColorBG {
    background-color: mat-color($warn);
  }
}

现在转到您用于主题材料2项目的theme.scss文件,如果您需要帮助,请查看以下内容:Material 2 Github - Theming guide

现在打开你的theme.scss并导入你的style.scss,因为我的theme.scss位于/src/app/theme.scss文件夹的根目录之内我必须先用它来引用我的/src/styles.scss全局样式像这样的文件;

@import '../styles';

然后我们必须实际包含我们在 ALL 我们的主题中创建的新自定义@mixin(如果您有多个像我一样,那么它会根据当前选定的主题更改颜色)。< / p>

  

将它包含在实际的角度材质主题包括上面,如下所示:

@include theme-color-grabber($theme);
@include angular-material-theme($theme);

如果您有像我这样的主题,请将其添加到相同位置,如下所示:

.light {
  $light-primary: mat-palette($mat-blue, 200,300, 900);
  $light-accent:  mat-palette($mat-light-blue, 600, 100, 800);
  $light-warn:    mat-palette($mat-red, 600);
  $light-theme: mat-dark-theme($light-primary, $light-accent, $light-warn);
  @include theme-color-grabber($light-theme);
  @include angular-material-theme($light-theme);

}

你可以看到我在include之上添加了我的theme-color-grabber,如果它高于或低于实际主题并不重要,因为它获得的主题颜色是主要的点。

我的整个themes.scss看起来像这样:

@import '~@angular/material/theming';
//We import our custom scss component here
@import '../styles';

@include mat-core();

$theme-primary: mat-palette($mat-red);
$theme-accent:  mat-palette($mat-deep-orange, A200, A100, A400);
$theme-warn:    mat-palette($mat-red);
$theme: mat-dark-theme($theme-primary, $theme-accent, $theme-warn);
//
@include theme-color-grabber($theme);
@include angular-material-theme($theme);
.light {
  $light-primary: mat-palette($mat-blue, 200,300, 900);
  $light-accent:  mat-palette($mat-light-blue, 600, 100, 800);
  $light-warn:    mat-palette($mat-red, 600);
  $light-theme: mat-dark-theme($light-primary, $light-accent, $light-warn);
  @include theme-color-grabber($light-theme);
  @include angular-material-theme($light-theme);

}

最后,我们现在可以在任何地方调用我们的主题颜色作为背景!例如,我给了mat-grid-tile&#39;主要&#39;通过简单地将其类设置为适当的类名来完成颜色(它不像color-&#39;&#39;参数那样采用其他元素,例如mat-toolbar):

编辑:在每个组件scss文件中,您需要import '<path-to>/theme.scss'才能将主题应用于该组件。不要在theme.scss中导入styles.scss,因为这会创建导入循环!

<mat-grid-list cols="4" rows="4" rowHeight="100px">
  <mat-grid-tile
    colspan="4"
    rowspan="5"
  class="primaryColorBG">
    <div fxLayout="column" fxLayoutAlign="center center">
      <h1 class="title-font">Callum</h1>
      <h1 class="title-font">Tech</h1>
    </div>
    <p>
      Ambitious and ready to take on the world of Information Technology,<br>
      my love for programming and all things I.T. has not wavered since I first got access<br>
      to my fathers computer at age 9.
    </p>
  </mat-grid-tile>

</mat-grid-list>

最后我们的结果会是这样的!:

红色主题有效 Red theme

蓝色主题有效 enter image description here

答案 1 :(得分:3)

我亲自将它们放在css4变量中,以便可以像这样不使用导入来使用它们

background: var(--color-primary)

这是如何设置css4变量

@import '~@angular/material/theming';
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat-core();

// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue. Available color palettes: https://material.io/design/color/
$app-primary: mat-palette($mat-blue);
$app-accent:  mat-palette($mat-orange);
$app-warn:    mat-palette($mat-red);
$app-success: mat-palette($mat-light-green);

// Create the theme object (a Sass map containing all of the palettes).
$app-theme: mat-light-theme($app-primary, $app-accent, $app-warn);

// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($app-theme);

$primary: map-get($app-theme, primary);
$accent: map-get($app-theme, accent);

:root {
  --color-primary: #{mat-color($app-primary)};
  --color-accent: #{mat-color($app-accent)};
  --color-warn: #{mat-color($app-warn)};
  --color-success: #{mat-color($app-success)};
}

现在颜色可以在css文件中使用,而无需导入

background: var(--color-primary)

答案 2 :(得分:1)

enter image description here

stackblitz here


最重要的部分:

在您的styles.scss 中(如果有,则为themes.scss):

@import '~@angular/material/theming';

@include mat-core();

@mixin define-css-classes($theme) {
    @include angular-material-theme($theme);

    $primary: map-get($theme, primary);
    $accent: map-get($theme, accent);
    $warn: map-get($theme, warn);
    $background: map-get($theme, background);
    $foreground: map-get($theme, foreground);

    // CSS THEME-DEPENDENT-STYLES ARE HERE:
    .theme-dependent-colors {
        background: mat-color($primary);
        color: mat-color($accent);
    }
}

/**
* Define your custom themes in this map. 
* The `key` of each member is the name of CSS class for that theme. 
* To better understand the schema of the map, see `@each` loop below and especially pay attention to `map-has-key()` functions.
*/ 
$app-themes: (
        indigo-pink : (primary-base: $mat-indigo, accent-base: $mat-pink),
        deeppurple-amber: (primary-base: $mat-deep-purple, accent-base: $mat-amber),
        pink-bluegrey : (primary-base: $mat-pink, accent-base: $mat-blue-gray, is-dark: true),
        purple-green : (primary-base: $mat-purple, accent-base: $mat-green, is-dark: true),
);

@each $css-class, $theme in $app-themes {
    $primary: if(map-has-key($theme, primary), map-get($theme, primary), mat-palette(map-get($theme, primary-base)));

    $accent: if(map-has-key($theme, accent), map-get($theme, accent), mat-palette(map-get($theme, accent-base)));

    $warn: if(map-has-key($theme, warn), map-get($theme, warn), mat-palette(
            if(map-has-key($theme, warn-base), map-get($theme, warn-base), $mat-red)
    ));

    .#{$css-class} {
        @include define-css-classes(mat-light-theme($primary, $accent, $warn));
    }

    .#{$css-class}-dark {
        @include define-css-classes(mat-dark-theme($primary, $accent, $warn));
    }

    .theme-primary.#{$css-class} {
        background-color: mat-color($primary);
    }

    ...
}

动态主题更改,在打字稿中使用setTheme()(请参见herehere):

import {Component, HostBinding} from '@angular/core';
import {OverlayContainer} from "@angular/cdk/overlay";

const THEME_DARKNESS_SUFFIX = `-dark`;

export class AppComponent {
    @HostBinding('class') activeThemeCssClass: string;
    isThemeDark = false;
    activeTheme: string;

    setTheme(theme: string, darkness: boolean = null) {
        if (darkness === null)
            darkness = this.isThemeDark;
        else if (this.isThemeDark === darkness) {
            if (this.activeTheme === theme) return;
        } else
            this.isThemeDark = darkness;

        this.activeTheme = theme;

        const cssClass = darkness === true ? theme + THEME_DARKNESS_SUFFIX : theme;

        const classList = this.overlayContainer.getContainerElement().classList;
        if (classList.contains(this.activeThemeCssClass))
            classList.replace(this.activeThemeCssClass, cssClass);
        else
            classList.add(cssClass);

        this.activeThemeCssClass = cssClass;
    }

    constructor(overlayContainer: OverlayContainer) {
        this.setThemeClass('indigo-pink', false); // Default theme
    }
}

请参阅stackblitz中的其他内容。


注意事项:在我的案例中,向应用程序添加8个动态材质主题(4个灯光+ 4个暗度)使styles.css的内置~420 kB大小增加了map.animateCamera(CameraUpdateFactory.newLatLng( LatLng(it.position.latitude, it.position.longitude))) Handler().postDelayed({ map.animateCamera(CameraUpdateFactory.zoomIn()) }, 500) (相对于一个静态材质主题) !

答案 3 :(得分:0)

  1. 将应用程序样式规则设置为SASS:
    在运行时更新自定义组件主题需要使用@mixin,因此您的应用程序样式规则应为 SASS (而不是CSS)。 您可以在此处阅读有关如何使用SASS配置Angular-Cli的信息:https://scotch.io/tutorials/using-sass-with-the-angular-cli

  2. 为自定义组件定义@mixin:
    在使用主题颜色的每个组件中,在其.scss文件中创建@mixin。为此组件提取所有颜色定义。并将它们移动到@mixin,如下所示:

  3. // --- file: my-component_1.scss ---
    @import '~@angular/material/theming'; // we need to add this so we could use Material functions
    @mixin set-theme-component-1($theme)
    {
      // Extract whichever individual palettes you need from the theme.
      $primary-palette: map-get($theme, primary);
      $accent-palette:  map-get($theme, accent);
      $warn-palette:    map-get($theme, warn);
    
      .component-container
      {
        background-color: mat-color($primary-palette); // use the mat-color function to extract the color from the palette
        border-color: mat-color($warn-palette);
      }
    }
    
    // Style rules that aren't theme/color related (size, font, etc)
    .component-container
    {
      width: 100%;
      ...
    }
    
    1. 定义主题文件:
      您需要定义一个主题文件(如果您还没有这样做)并调用我们在此文件中定义的@mixin,如下所示:
    2. // --- file: app.theme.scss ---
      @import '~@angular/material/theming';
      @include mat-core(); // include this only once in your code!!!
      
      // each custom component that uses theme colors will be imported here - we need there @mixin
      @import './some-path/some-folder/my-component_1'; // no need to specify .scss suffix
      
      @mixin set-theme($theme) // define a new @mixin that will be invoked each time the theme is changed
      {
        @include set-theme-component-1($theme); // invoke the mixin we defined for component_1
        // repeat this for each component that uses theme colors
      }
      
      // define your themes:
      .theme-light
      {
        $light-primary: mat-palette($mat-indigo);
        $light-accent:  mat-palette($mat-pink, A200, A100, A400);
        $light-warn:    mat-palette($mat-red);
        $light-theme:   mat-light-theme($light-primary, $light-accent, $light-warn);
      
        @include angular-material-theme($light-theme);
        @include set-theme($light-theme); // once the theme was set, invoke the mixin
      }
      
      .theme-dark
      {
        $dark-primary:  mat-palette($mat-teal, A400);
        $dark-accent:   mat-palette($mat-grey, 800);
        $dark-warn:     mat-palette($mat-red, 700);
        $dark-theme:    mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
      
        @include angular-material-theme($dark-theme);
        @include set-theme($dark-theme); // once the theme was set, invoke the mixin
      }
      
      

      那是: - )

      他们需要执行一些额外的步骤,以便实时主题工作(它们与自定义组件无关,因此我只会快速抛出它们。)
      - 创建一个将保存当前主题的ThemeService。此服务需要更新 OverlayContainer (Angular材料使用此容器作为弹出窗口和下拉列表等模式的背景)。
      - 将主题类(theme-dark或任何其他类)添加到DOM中的一个根元素 - 将类mat-app-background添加到DOM中的一个根元素。这将根据主题更改背景颜色和字体颜色 - 为了更好的软件设计 - 如果你有很多主题,拆分主题文件可能是维护海豚的好主意。

      您可以在这里继续阅读: https://material.angular.io/guide/theming

      或在那里看到Github项目:https://github.com/angular/material2/blob/master/src/lib/core/theming/_theming.scss

答案 4 :(得分:0)

我绝对是新手,也许这是一种过时的做法,对这种情况没有用,或者是一种资源消耗性的解决方案,但是在 myangularthemefile.scss 中,我创建了以下类: / p>

@import '~@angular/material/theming';
@include mat-core();

...

.matcolorprimary{
    color: mat-color($mitjans-primary)
}

.matcoloraccent {
    color: mat-color($mitjans-accent);
}

.matcolorwarn {
    color: mat-color($mitjans-warn);
}

然后将它们添加到组件模板所需的html元素中。

我认为为背景颜色创建相同的结构很容易...

这是在小项目的每个影子dom组件样式表中包括Sass伪像的替代方法吗?

答案 5 :(得分:0)

如果你想根据你的主题改变颜色,你可以简单地定义相同的变量,嵌套在定义你的主题的每个类中。例如,在我的应用程序中,主题是通过将一个类分配给我的应用程序的外部容器来设置的。因此,嵌套在每个“主题类”中,我可以将相同的变量分配为不同的值。因此,当分配给整个应用程序的“主题类”发生变化时,我的变量的值也会随之变化:

.app-light-theme {
  @include angular-material-theme($theme);
  * {
     --my-variable-color: yellow;
    }
}

.app-dark-theme {
  @include angular-material-theme($altTheme);
  * {
    --my-variable-color: purple;
  }
}

然后在我的应用程序中的任何 css 文件中,我都可以通过使用 var() 来使用我的变量:

background-color: var(--my-variable-color);

并且颜色会根据应用设置的主题而改变。

您只需在每个主题中设置 --primary --accent--warn 变量,即可使用主题的主色、强调色和警告色。