如何在Angular 2中有条件地添加动画

24

我有一个表单组件,其中有一些字段,我希望在这些字段出现在表单中时对它们进行动画处理,但并不是每个字段都需要动画。

<div *ngFor="let field of form.Fields">
    <div [ngSwitch]="field.Type" [@slideOut]>
        <!-- more field stuff -->
    </div>
</div>

使用其他属性,我可以做出如下操作[attr.required]="field.Required" 但是 [attr.@slideOut] 似乎不起作用。

理想情况下,我希望在我的字段上有一个动画属性,这样我就可以像这样传递动画[@field.Animation] ,但是我找不到任何关于如何实现类似功能的文档。有什么建议吗?


你的slideOut有哪些动画状态?你应该使用类似[@slideOut] = "<state_name>"或类似的东西,其中state_name可以通过动态方式确定(例如通过返回名称的方法)或静态方式确定(例如只是硬编码字符串)。 - danimal
我可以尝试这样做,现在slideOut是一个void => *动画。 - Devcon
然后开始设置[@slideOut] =“'test'”或类似的内容-您动画定义中的*应该会捕获它! - danimal
2个回答

23

要有条件地启用或禁用动画触发器,请使用[@.disabled],如https://angular.io/api/animations/trigger#disabling-animations文档中所述。

以OP中的示例为例,如果每个字段都有一个布尔值的'required'属性,并且只有在这个属性为true时才应用动画,则代码可能是:

<div *ngFor="let field of form.Fields">
    <div [@slideOut] [@.disabled]="!field.required">
        <!-- more field stuff -->
    </div>
</div>

值得一提的是,在组件上使用 [@.disabled] 还会禁用任何子组件上的动画,例如,材料菜单的出现将不再有动画效果。

必要时,可以通过在父动画中使用条件语句将动画的持续时间设置为 0 来避免这种情况,这样就可以(视觉上)去除动画,而不会影响任何子组件。

模板:

<div *ngFor="let field of form.Fields">
    <div [@slideOut]="field.required ? {value:'', params:{duration : 200}} : {value:'', params:{duration : 0}}">
        <!-- more field stuff -->
    </div>
</div>

动画:

trigger('slideOut', [
    transition(':enter', [
        style({ opacity: '0' }),
        animate('{{duration}}ms cubic-bezier(0.4, 0.0, 0.2, 1)'),
        style({ opacity: '1' })
    ])
])

19

我遇到过类似的问题,发现需要采用稍微不同的方法。

在Angular中,动画与状态相对应。因此,你不需要在HTML中为你的动画定义一个不同的触发器,而是需要在你的组件类中定义多个状态以供你的触发器监视。并且,你需要通过设置动画所关联对象的状态来触发动画,而不是直接从方法中触发动画。

例如,导入必要模块后,我可能会在组件装饰器中定义以下内容:

@Component({
  selector: 'app-some-animated',
  templateUrl: './some.component.html',
  styleUrls: ['./some-animated.component.scss'],
  animations: [
    trigger('flyInOut', [
      transition("void => fly", [
        animate(300, keyframes([
          style({transform: 'translateX(100%)', opacity: 0}),
          style({transform: 'translateX(0)', opacity: 1})
        ]))
        ]
      )
    ]),
    trigger('flyInOut', [
      transition("void => fade", [
          animate(300, keyframes([
            style({opacity: 0}),
            style({opacity: 1})
          ]))
        ]
      )
    ])
  ]
})

在这个例子中,我让元素实例化后立即发生动画。而在ngOnInit()方法中,我将this.watchMe设置为"fly"或"fade"。

在HTML中,我像这样附加了flyInOut触发器:

<div [@flyInOut]="watchMe">
  Some content...
</div>

在您的情况下,您可能想要将所需状态添加到字段对象中或将其作为* ngFor的可迭代条件。

coursetro的这篇文章有一个很好的解释和视频。


3
我接受这个答案,因为这是我找到的唯一方法。我不喜欢管理动画状态,尤其是在这种情况下,因为我需要为数组中的每个项目都这样做。我觉得奇怪的是,Angular有这两种形式的动画(实例和状态)。我也不喜欢唯一一个我不能动态添加的属性是由Angular团队制作的 :P 哦,那好吧。 - Devcon
4
同意这个解决方案有点不太稳定。但这就是 Angular,它经常让人觉得自己并没有在开发,只是在配置别人的代码。 - user2528534
请问您能否添加一个组件功能的示例,该功能可以改变watchme的状态? - tatsu
谢谢回答。只是需要注意:我们需要使用变量(例如,如果我们使用[@flyInOut] =“'fly'”,它将无法按预期工作)。 - Smaillns

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接