【问题标题】:Change angular material progress bar color from code从代码更改角度材质进度条颜色
【发布时间】:2018-09-14 10:54:35
【问题描述】:

我需要动态更改angular material progress bar 的颜色。 我意识到这并不是那么简单,那么最好的方法是什么?

要求:

  1. 我将从外部 API 接收颜色十六进制代码。所以我无法创建一组预定义的主题
  2. 背景颜色为白色。所以,我只需要一种颜色,而不是整个调色板(更亮、更暗)的颜色。

相关链接:(1)

【问题讨论】:

标签: angular angular-material


【解决方案1】:

我们可以创建一个属性指令,它接受颜色值并为我们覆盖<mat-progress-bar> 的默认样式。

这是一个工作演示:https://stackblitz.com/edit/material-progress-bar-color-directive

这里有一个简单的解释:

如果我们在开发者工具中检查<mat-progress-bar>。我们会发现进度条的颜色是在::after 伪元素中定义的,如下所示。

.mat-progress-bar-fill::after {
    background-color: #3f51b5;
}

而且我们已经知道,使用 DOM querySelector() 方法直接操作伪元素是不可能的。但是我们可以添加新的样式,这些样式也可以为伪元素设置规则。结帐此线程以获取更多详细信息。 https://stackoverflow.com/a/21709814/1160236

因此,我们可以创建一个指令来为我们添加新样式。

import { Directive, Input, OnChanges, SimpleChanges, ElementRef } from '@angular/core';

@Directive({
  selector: '[appProgressBarColor]'
})
export class ProgressBarColor implements OnChanges{
  static counter = 0;

  @Input() appProgressBarColor;
  styleEl:HTMLStyleElement = document.createElement('style');

  //generate unique attribule which we will use to minimise the scope of our dynamic style 
  uniqueAttr = `app-progress-bar-color-${ProgressBarColor.counter++}`;

  constructor(private el: ElementRef) { 
    const nativeEl: HTMLElement = this.el.nativeElement;
    nativeEl.setAttribute(this.uniqueAttr,'');
    nativeEl.appendChild(this.styleEl);
  }

  ngOnChanges(changes: SimpleChanges): void{
    this.updateColor();
  }

  updateColor(): void{
    // update dynamic style with the uniqueAttr
    this.styleEl.innerText = `
      [${this.uniqueAttr}] .mat-progress-bar-fill::after {
        background-color: ${this.appProgressBarColor};
      }
    `;
  }

}

如您所见,我们在这里所做的只是创建一个新的HtmlStyleElement 并将其添加到宿主元素中。

updateColor() 方法中,我们正在更新我们附加的样式标签的innerText。请注意,我们在这里使用了一个带有唯一属性的属性选择器,以将样式的范围最小化到主机。因为我们只想覆盖我们应用了指令的进度条的样式。

你可以像这样在你的模板中使用这个指令。

<mat-progress-bar [appProgressBarColor]="'orange'"
                  mode="determinate" 
                  value="40"></mat-progress-bar>

我希望这会有所帮助。

【讨论】:

  • 在我向原生元素和样式添加类名之前,我无法让它在 Angular 11 中工作。例如,“nativeEl.classList.add('progress-bar-custom-color');”和 ".progress-bar-custom-color[${this.uniqueAttr}] .mat-progress-bar-fill::after"...
【解决方案2】:

更新:

避免使用深度, TL;DR:Deep 在技术上是无效的(例如,deeprecated :p)

更多信息请参考:The use of /deep/ and >>> in Angular 2

现在,要更改垫子进度条的颜色,

转到您的 styles.scss 文件(或项目中的主 css/scss 文件)

添加这个类 -->

.green-progress .mat-progress-bar-fill::after {
    background-color: green !important;
}

你的 mat-progress 应该使用上面的类,比如 -->

<mat-progress-bar class="green-progress" mode="indeterminate"></mat-progress-bar>

【讨论】:

  • 实现它的最佳响应:更短更简单也鼓励避免使用'deep'
  • 这实际上挽救了我的一天。非常感谢。
【解决方案3】:

我遇到了这个问题,但所提出的解决方案都没有真正解决我所理解的问题。经过一些不同的思考方式之后,我相信我找到了一个可管理的解决方案,用于在 API 调用(或用户输入)之前动态更改 mat-progress-bar 的颜色时它们是未知的。我创建了一个example on stackblitz 来玩,但它最终的工作原理是这样的:

  1. 在初始化时,创建一个 style HTMLElement 供您稍后引用。
  2. 在您想要的任何触发器上(在示例中,它是输入值的更改)清除样式元素,将颜色重新分配给自定义 css,然后重新附加到 head
// in app.component.ts

  styleElement: HTMLStyleElement;
  colors : Array<string> = ["#ff00ff", "#00ff00"];

changeColors() {
  const head = document.getElementsByTagName('head')[0];
  const css = `
  .style1 .mat-progress-bar-fill::after {
    background-color: ${this.colors[0]} !important;
  }

  .style2 .mat-progress-bar-fill::after {
    background-color: ${this.colors[1]} !important;
  }
  `;
  this.styleElement.innerHTML = '';
  this.styleElement.type = 'text/css';
  this.styleElement.appendChild(document.createTextNode(css));
  head.appendChild(this.styleElement);

}

ngOnInit() {
  this.styleElement = document.createElement('style');
  this.changeColors();
}
<!-- In app.component.html -->
<p>
  <mat-progress-bar mode="determinate" value=70 class="style1"></mat-progress-bar>
</p><p>
  <mat-progress-bar mode="determinate" value=40 class="style2"></mat-progress-bar>
</p>
<div><mat-form-field><input matInput type="color" placeholder="Style 1" [(ngModel)]="colors[0]" (change)="changeColors()" /></mat-form-field>
<mat-form-field><input matInput type="color" placeholder="Style 2" [(ngModel)]="colors[1]" (change)="changeColors()" /></mat-form-field></div>

【讨论】:

    【解决方案4】:

    mat-progress-bar

    /deep/ .mat-progress-bar-fill::after {
        background-color: green;
    }
    
    /deep/ .mat-progress-bar-buffer {
        background: #E4E8EB;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-23
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多