使用CSS变量创建角度材质主题

使用CSS变量创建角度材质主题,css,angular,sass,angular-material,Css,Angular,Sass,Angular Material,我正在做一个需要在运行时可主题化的项目。所以我创建了一个主题系统,它将SCSS变量与CSS变量相结合。 这就是它的样子 :root { --primary-color: 196; } // Primary $primary-100: hsl(var(--primary-color), 90%, 98%); $primary-400: hsl(var(--primary-color), 90%, 65%); $primary-main: hsl(var(--primary-color),

我正在做一个需要在运行时可主题化的项目。所以我创建了一个主题系统,它将SCSS变量与CSS变量相结合。 这就是它的样子

:root {
  --primary-color: 196;
}


// Primary
$primary-100: hsl(var(--primary-color), 90%, 98%);
$primary-400: hsl(var(--primary-color), 90%, 65%);
$primary-main: hsl(var(--primary-color), 90%, 50%);
$primary-700: hsl(var(--primary-color), 90%, 30%);
$primary-900: hsl(var(--primary-color), 90%, 10%);
虽然这在我的自定义组件上工作得很好,但我很难让它与材质设计主题系统一起工作

我的想法是,我将按照Angular material文档中的说明创建主题,并使用SCSS变量,而不是使用静态颜色。这就是我的theme.scss文件的外观

@import '~@angular/material/theming';
@import 'var.scss';

@include mat-core();

$shop-primary: (
  50: $primary-100,
  100: $primary-100,
  200: $primary-200,
  300: $primary-300,
  400: $primary-400,
 // ..... all other colors
  contrast: (
    50: $black-87-opacity,
    100: $black-87-opacity,
    200: $black-87-opacity,
     // ..... all other colors
  )
);


$shop-app-primary: mat-palette($shop-primary);
$shop-app-accent:  mat-palette($shop-primary);
$shop-app-warn: mat-palette($shop-primary);


$shop-app-theme: mat-light-theme($shop-app-primary, $shop-app-accent, $shop-app-warn);

@include angular-material-theme($shop-app-theme);
我得到一个错误:

 Argument `$color` of `rgba($color, $alpha)` must be a color
这可能是因为角度材质混合所需的是
颜色,而不是
hsl()


所以我的问题是,如何使用运行时CSS变量创建自定义材质主题?

所以。。。css变量是运行时变量,而不是编译时变量。萨斯不知道该拿他们怎么办。您应该能够使用SCS的${}插值来重构css变量,并使所有内容都保持不变


如果您升级到@angular/material 7.3.4,CSS变量将主要起作用。只有撕裂和其他使用不透明的东西需要一点修复。我在我的项目中使用rgba(),但它也应该适用于hsla()

包括:

@function mat-color($palette, $hue: default, $opacity: null) {
    @if type-of($hue) == number and $hue >= 0 and $hue <= 1 {
        @return mat-color($palette, default, $hue);
    }

    $color: map-get($palette, $hue);

    @if (type-of($color) != color) {
        @if ($opacity == null){
            @return $color;
        }

        // Here is the change from the original function:
        // If the $color resolved to something different from a color, we assume it is a CSS variable
        // in the form of rgba(var(--rgba-css-var),a) and replace the 'a' value.
        @return #{str-slice($color, 0, str-index($color, ',')) + $opacity + ')'};
    }

    @return rgba($color, if($opacity == null, opacity($color), $opacity));
}
并按如下方式定义您的颜色:

--primary-color-50-parts: 0,158,224;
// ... all other colors

$color-primary: (
    50: rgba(var(--primary-color-50-parts), 1),
    // ... all other colors
);
50: hsla(var(--primary-color), 90%, 98%, 1);
如果在地图中定义颜色,如下所示:

--primary-color-50-parts: 0,158,224;
// ... all other colors

$color-primary: (
    50: rgba(var(--primary-color-50-parts), 1),
    // ... all other colors
);
50: hsla(var(--primary-color), 90%, 98%, 1);
然后,您需要将sass函数中的str index($color,,')更改为查找字符串中最后一个“,”的内容。不幸的是,我的sass知识只涵盖了最基本的内容,我不知道如何做到这一点://

我创建了一个新的sass来简化这一点

您可以这样使用它:

  • 安装:

    npm i angular-material-css-vars -S
    
  • 然后删除任何现有的
    @import'~@angular/material/theming'来自主样式表文件

  • 将以下内容添加到主样式表:

    @import '~angular-material-css-vars/main';
    @include initMaterialCssVars();
    
  • 更改主主题颜色,如下所示:

    从“角度材质css变量”导入{materialcssversservice};
    导出类SomeComponentOrService{
    建造商(公共材料服务:材料服务){
    常量十六进制='#3f51b5';
    此.materialcsvarsService.changePrimaryColor(十六进制);
    }
    }
    

  • 我创建了一个小的库材料主题创建者

    您可以为角度应用程序设置主题,也可以使用此方法创建主题

    NPM:

    文件:

    npm i材料主题创建者

    @import "~material-theme-creator/ngx-mtc";
    @import '~@angular/material/theming';
    
    @include mat-core();
    @include ngx-mtc-init();
    
    $primary-map: ngx-mtc-create-theme-map('primary');
    $accent-map: ngx-mtc-create-theme-map('accent');
    $warn-map: ngx-mtc-create-theme-map('warn');
    
    :root {
      --is-dark-theme: 1; // Is dark theme? 1 or 0;
      @include ngx-mtc-theme-base(); // Creates base colors
    
      // Creates theme colors
      @include ngx-mtc-create-variables-from-color('primary', #009688, 38%);
      @include ngx-mtc-create-variables-from-color('accent', #2196f3, 57%);
      @include ngx-mtc-create-variables-from-color('warn', #f44336, 62%);
    }
    
    // Creates Angular Material Theme
    @include angular-material-theme(
      ngx-mtc-custom-theme(
        mat-palette($primary-map),
        mat-palette($accent-map),
        mat-palette($warn-map)
      )
    );
     
    
    第二个主题代码:

    .second-theme {
      --is-dark-theme: 0;
      @include ngx-mtc-update-theme('primary', #142148, 45%);
      @include ngx-mtc-update-theme('accent', #658e14, 50%);
      @include ngx-mtc-update-theme('warn', #750101, 50%);
    }
    

    您可以将它与Angular Material或SCSS或纯CSS一起使用

    我刚刚使用hsl()SCSS函数测试了我的项目,它工作正常。您的angular.json中是否有“StylePreprocessions”:{“includePaths”:[“src”,“src/assets/scss”]}属性,以便可以全局拾取var.scs?您确定您正确使用了
    mat调色板
    ?我找不到将数组传递给的示例it@Budhead2004我的var.scss包括在内,非常好。我到处都在使用它。@Budhead2004您是否将CSS变量传递给hsl函数?您能告诉我传递给hsl()函数的$var的内容吗@Dirk他正确地使用了mat palette功能,这正是我的自定义主题的设置方式。我不需要SCSS知道如何处理它,SCSS只需将其放置在指定的值上,浏览器就会对其进行解释。其次,我之所以希望这样做,是因为我应该能够在运行时更改主题。哇!听起来不错,我没有时间去查看,但这似乎是合法的!与
    @函数colortoviable($hexColor){@return“{red($hexColor)}、{green($hexColor)}、{blue($hexColor)}”}
    和更高版本的
    --颜色主打火机:{colortoviable(#ff0000)}为了避免手动rgb转换,我们可以将字体样式应用到您提到的库中吗?