简体   繁体   English

如何让 Angular 组件动画遵循 CSS 类更改,而不是静态样式?

[英]How can I make Angular component animations follow CSS class changes, rather than static styles?

I've created a block-cursor date/time input field that uses Angular states and animations to indicate both ongoing states (like being disabled) or animated transitional states (like a red flash when an invalid keystroke has been entered).我创建了一个块光标日期/时间输入字段,它使用 Angular 状态和动画来指示正在进行的状态(如被禁用)或动画过渡状态(如输入无效按键时的红色闪光)。 These input fields can be seen in use here: https://skyviewcafe.com/这些输入字段可以在这里看到: 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))
]);

The above animations are defined in an abstract superclass so that concrete subclasses can use them like this:上面的动画定义在一个抽象的超类中,以便具体的子类可以像这样使用它们:

@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 {
  ...

First of all, I'd prefer to cut the number of display states in half.首先,我更愿意将显示状态的数量减少一半。 I consider it a hack to have to have all of those dark_ -prefixed states.我认为必须拥有所有这些dark_前缀状态是一种黑客行为。 I'd rather have these colors automatically update, as they do for DOM elements, simply by adding the tbw-dark-mode class to the body of my HTML document.我宁愿让这些颜色自动更新,就像它们对 DOM 元素所做的那样,只需将tbw-dark-mode类添加到我的 HTML 文档的正文中即可。

I'm also limited to supporting only the two pre-defined modes, light and dark.我也仅限于支持两种预定义的模式,亮和暗。 Users can customize both the light mode and the dark mode, but a third mode, or generalized "skins" would be impossible.用户可以自定义亮模式和暗模式,但第三种模式或通用“皮肤”是不可能的。

Timing also matters.时机也很重要。 These colors are generated once during the initialization of the application in which my components are embedded, and I see no access to an Angular API that allows these state definitions to be updated later.这些颜色在嵌入我的组件的应用程序的初始化期间生成一次,并且我看不到对允许这些状态定义稍后更新的 Angular API 的访问。

The function getBackgroundColor() at least allows me to check once how colors have been defined at start-up, but it's not perfect (iOS Safari messes up and thinks everything is transparent), so I have to define fixed fallback values which can't be updated from a style sheet.函数getBackgroundColor()至少允许我在启动时检查颜色是如何定义的,但它并不完美(iOS Safari 搞砸了,认为一切都是透明的),所以我必须定义固定的后备值,这些值不能从样式表更新。

I did discover a disgusting hack to get some dynamic updating of colors, but it's not something I'd want to rely on!我确实发现了一个令人作呕的 hack 来动态更新颜色,但这不是我想要依赖的东西! Instead of using a string for each color, I defined a dynamic color object like this:我没有为每种颜色使用一个字符串,而是定义了一个动态颜色对象,如下所示:

class DynamicColor extends String {
  constructor(private colorKey: string) {}

  // ...

  toString(): string {
    return this.colorTable[colorKey];
  }
}

Even that requires some forced type coercion to string , and forced screen refreshing to make changes take effect.即便如此,也需要对string一些强制类型强制,并强制刷新屏幕以使更改生效。

Is there a better way?有没有更好的办法? A way to use CSS classes instead of statically-defined styles?一种使用 CSS 类而不是静态定义样式的方法? An API I haven't found yet to update the animations which are installed by the @Component decorator?我还没有找到更新@Component装饰器安装的动画的 API?

Why not use CSS variables for the colors?为什么不为颜色使用 CSS 变量?

https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties

You can then just change, for example the background color from --color-1 to --color-2 in the state animations.然后,您可以更改,例如在状态动画中将背景颜色从--color-1更改为--color-2

And in a separate part of your application you can change the definitions of these variables using something like this:在应用程序的单独部分中,您可以使用如下方式更改这些变量的定义:

@Component({ /*…*/ })
export class MyComponent {
  @HostBinding("style.--color-1")
  private color1: string;

  changeColor1(value: string) {
   this.color1 = value;
  }
}

Note: Support for CSS variables is pretty good as long as you don't need to support IE: https://caniuse.com/css-variables注意:只要不需要支持 IE,对 CSS 变量的支持就不错了: https : //caniuse.com/css-variables

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Angular CSS 中的组件 Styles - Angular Component Styles in CSS 如何使用css3动画制作这个Jquery animate()? - How can I make this Jquery animate() with css3 animations? 如何在React中导入特定于组件的CSS样式? - How can I import component-specific css styles in React? 如何动态设置 CSS class Angular 中的元素列表 ZA2F2ED4F8EBC2CBB1D4C21A29DC4 组件? - How can I dynamically set a CSS class list of an element in Angular from the class component? 如何通过 angular 中的组件加载 static html? - How can i load static html through a component in angular? 如何在Angular 5中从父组件继承子组件中的css样式 - How to inherit css styles in child component from parent in Angular 5 什么时候可以在react / react中使用reactDOM /如何使某些东西出现在屏幕上而不是在consoke中? - When can you use reactDOM in react/how can i make something appear on screen rather than in consoke? 如何使 classList.toggle 遵循类的 CSS - How to make classList.toggle follow class's CSS 角4路由添加一个组件而不是替换它 - angular 4 routing adding a component rather than replacing it CSS:我怎么能有一个“分散显示单词”而不是html默认显示上/下? - CSS: How can I have a “scatter display of words” rather than the html default display up/down?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM