如何让 Angular 组件动画跟随 CSS 类的变化,而不是静态样式?
Posted
技术标签:
【中文标题】如何让 Angular 组件动画跟随 CSS 类的变化,而不是静态样式?【英文标题】:How can I make Angular component animations follow CSS class changes, rather than static styles? 【发布时间】:2021-10-05 10:35:50 【问题描述】:我创建了一个块光标日期/时间输入字段,它使用 Angular 状态和动画来指示正在进行的状态(如被禁用)或动画过渡状态(如输入无效击键时的红色闪烁)。这些输入字段可以在这里看到:https://skyviewcafe.com/
export const BACKGROUND_ANIMATIONS = trigger('displayState', [
state('error', style( backgroundColor: getBackgroundColor(ERROR_BACKGROUND, '#F67') )),
state('normal', style( backgroundColor: getBackgroundColor(NORMAL_BACKGROUND, 'white') )),
state('confirm', style( backgroundColor: getBackgroundColor(CONFIRM_BACKGROUND, '#6C6') )),
state('warning', style( backgroundColor: getBackgroundColor(WARNING_BACKGROUND, '#FC6') )),
state('view-only', style( backgroundColor: getBackgroundColor(VIEW_ONLY_BACKGROUND, 'black') )),
state('disabled', style( backgroundColor: getBackgroundColor(DISABLED_BACKGROUND, '#CCC') )),
state('dark-error', style( backgroundColor: getBackgroundColor(ERROR_BACKGROUND, '#C36', true) )),
state('dark-normal', style( backgroundColor: getBackgroundColor(NORMAL_BACKGROUND, '#333', true) )),
state('dark-confirm', style( backgroundColor: getBackgroundColor(CONFIRM_BACKGROUND, '#292', true) )),
state('dark-warning', style( backgroundColor: getBackgroundColor(WARNING_BACKGROUND, '#B80', true) )),
state('dark-view-only', style( backgroundColor: getBackgroundColor(VIEW_ONLY_BACKGROUND, '#0A0', true) )),
state('dark-disabled', style( backgroundColor: getBackgroundColor(DISABLED_BACKGROUND, '#444', true) )),
transition('normal => error', animate(FLASH_DURATION)),
transition('error => normal', animate(FLASH_DURATION)),
transition('normal => confirm', animate(FLASH_DURATION)),
transition('confirm => normal', animate(FLASH_DURATION)),
transition('warning => error', animate(FLASH_DURATION)),
transition('error => warning', animate(FLASH_DURATION)),
transition('dark-normal => dark-error', animate(FLASH_DURATION)),
transition('dark-error => dark-normal', animate(FLASH_DURATION)),
transition('dark-normal => dark-confirm', animate(FLASH_DURATION)),
transition('dark-confirm => dark-normal', animate(FLASH_DURATION)),
transition('dark-warning => dark-error', animate(FLASH_DURATION)),
transition('dark-error => dark-warning', animate(FLASH_DURATION))
]);
上面的动画被定义在一个抽象的超类中,以便具体的子类可以像这样使用它们:
@Component(
selector: 'tbw-time-editor',
animations: [BACKGROUND_ANIMATIONS],
templateUrl: '../digit-sequence-editor/digit-sequence-editor.directive.html',
styleUrls: ['../digit-sequence-editor/digit-sequence-editor.directive.scss', './time-editor.component.scss'],
providers: [ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TimeEditorComponent), multi: true ,
provide: NG_VALIDATORS, useExisting: forwardRef(() => TimeEditorComponent), multi: true ]
)
export class TimeEditorComponent extends DigitSequenceEditorDirective<number> implements OnInit
...
首先,我希望将显示状态的数量减半。我认为必须拥有所有这些dark_
-prefixed 状态是一种黑客行为。我宁愿让这些颜色自动更新,就像它们对 DOM 元素所做的那样,只需将 tbw-dark-mode
类添加到我的 HTML 文档的正文中即可。
我也仅限于支持两种预定义模式,明暗模式。用户可以自定义亮模式和暗模式,但第三种模式或通用“皮肤”是不可能的。
时间也很重要。这些颜色在嵌入我的组件的应用程序初始化期间生成一次,我看不到对允许稍后更新这些状态定义的 Angular API 的访问。
getBackgroundColor()
函数至少允许我在启动时检查颜色是如何定义的,但它并不完美(ios Safari 搞砸了,认为一切都是透明的),所以我必须定义固定的后备值无法从样式表更新。
我确实发现了一个令人作呕的 hack 来获得一些颜色的动态更新,但这不是我想要依赖的东西!我没有为每种颜色使用一个字符串,而是定义了一个动态颜色对象,如下所示:
class DynamicColor extends String
constructor(private colorKey: string)
// ...
toString(): string
return this.colorTable[colorKey];
即使这需要对string
进行强制类型强制转换,并强制刷新屏幕以使更改生效。
有没有更好的方法?一种使用 CSS 类而不是静态定义样式的方法?我还没有找到更新 @Component
装饰器安装的动画的 API?
【问题讨论】:
【参考方案1】:为什么不使用 CSS 变量来表示颜色?
https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
然后您可以在状态动画中将背景颜色从--color-1
更改为--color-2
。
在应用程序的单独部分中,您可以使用以下方式更改这些变量的定义:
@Component( /*…*/ )
export class MyComponent
@HostBinding("style.--color-1")
private color1: string;
changeColor1(value: string)
this.color1 = value;
注意: 对 CSS 变量的支持很好,只要你不需要支持 IE:https://caniuse.com/css-variables
【讨论】:
当我深入研究 Angular 代码的内部时,这些颜色分配归结为这行代码:element.style[camelProp] = styles[prop];
。以这种方式设置颜色时,没有适当的机制来解释 CSS 变量。这是在样式表级别完成的。只有具体定义的颜色才能在上面的代码中起作用。以上是关于如何让 Angular 组件动画跟随 CSS 类的变化,而不是静态样式?的主要内容,如果未能解决你的问题,请参考以下文章