如何用Animations系统制作reinitialize/retrigger个动画?

How to reinitialize/retrigger animations made with Animations system?

我是 @angular/animations 的新手,现在我遇到了一些事情。我有一个简单的列表,当你 select 一个项目时它显示一个子列表,两个列表有相同的动画,但是如果 select 第一个列表中的不同项目第二个列表不会再次动画.我已经尝试将第二个列表分配给 null 然后给出新值,认为这足以让动画再次触发。

我正在使用的解决方法是 setTimeout 在分配新值之前等待 100 毫秒,它工作正常,但屏幕闪烁,这是我的代码:

我的 COMPONENT.HTML:

<ion-list>
    <!-- FIRST LIST -->
    <ion-item-group>
      <ion-item-divider color="light">By Animal</ion-item-divider>
      <ion-item [@listAnimation]="services.length" class="scrollable-x">
        <ion-avatar *ngFor="let serv of services" item-start (tap)="setSelectedType(serv)">
          <img src="/path/to/image.png">
          <p>{{serv.type}}</p>
        </ion-avatar>
      </ion-item>
    </ion-item-group>

    <!-- SECOND LIST: DYNAMIC LIST -->
    <ion-item-group *ngIf="selectedType">
      <ion-item-divider color="light">Services: {{selectedType}}</ion-item-divider>
      <ion-item [@listAnimation]="selectedTypeServices.length" class="scrollable-x">
        <ion-avatar *ngFor="let serv of selectedTypeServices" item-start>
          <img src="/path/to/image.png">
          <p>{{serv.name}}</p>
        </ion-avatar>
      </ion-item>
    </ion-item-group>
  </ion-list>

我的 COMPONENT.TS:

import { IonicPage, NavController, NavParams } from "ionic-angular";
import { trigger, style, transition, animate, keyframes, query, stagger } from "@angular/animations";

@IonicPage()
@Component({
  selector: "page-agendar",
  templateUrl: "agendar.html",
  animations: [
    trigger("listAnimation", [
      transition("* => *", [
        query(":enter", style({ opacity: 0 }), { optional: true }),

        query(
          ":enter",
          stagger("300ms", [
            animate(
              ".7s ease-in",
              keyframes([
                style({ opacity: 0, transform: "translateX(-75%)", offset: 0 }),
                style({
                  opacity: 0.5,
                  transform: "translateX(25px)",
                  offset: 0.3
                }),
                style({ opacity: 1, transform: "translateY(0)", offset: 1.0 })
              ])
            )
          ]),
          { optional: true }
        )
      ])
    ])
  ]
})
export class AgendarPage {
  public services: Array<{ type: string; services: Array<{ name: string }>}> = [];

  public selectedType: string;
  public selectedTypeServices: any[];

  constructor(){}

  setSelectedType = service => {
    this.selectedType = null;
    setTimeout(() => {
      this.selectedTypeServices = service.services;
      this.selectedType = service.type;
    }, 100);
  };
}

那么有没有办法重新初始化或重新触发动画呢?也许我缺少某些选项,trigger() 以外的其他功能或类似的功能?

我认为您的动画不是 "retriggering" 的主要原因是您对 angular 动画的状态配置。 angular中有两种处理动画的方法:

1.) 状态方法

trigger('cube', [
  state('front', style({
    transform: 'rotateX(0deg)',
  })))

2.) 过渡方法

trigger(
  'myAnimation',
  [
    transition(
    ':enter', [
      style({transform: 'translateY(-100%)', opacity: 0}),
      animate('500ms', style({transform: 'translateY(0)', 'opacity': 1}))
    ]
  ))

您似乎将两者混为一谈,我相信这就是您的问题所在。

如果您为 html 使用 State 方法,您可以这样说:

HTML

<div [@cube]="state">

打字稿

trigger('cube', [
  // States that can occur from viewing the front panel
  state('front', style({
    transform: 'rotateX(0deg)',
  })),
  state('bottom', style({
    transform: 'rotateX(90deg) translateY(-50vh) translateZ(50vh)',
  }))
  // Front animations when landing on page
  transition('front => bottom', animate('1500ms ease-in-out')),
  transition('bottom => front', animate('1500ms ease-in-out'))
])

例如,您可以将 ngOnInit() 的状态初始化为底部或前面,然后打开点击或类似的东西。请注意,动画的发生是因为元素正在变化 "states" 并且该变量正在指示变化。

如果您选择转换方法,您将得到如下内容:

HTML

<div *ngIf="hasUpload=='yes'" [@myAnimation]>

打字稿

trigger(
  'myAnimation',
  [
    transition(
    ':enter', [
      style({transform: 'translateY(-100%)', opacity: 0}),
      animate('500ms', style({transform: 'translateY(0)', 'opacity': 1}))
    ]
  ),
  transition(
    ':leave', [
      style({transform: 'translateY(0)', 'opacity': 1}),
      animate('500ms', style({transform: 'translateY(-100%)', 'opacity': 0})),
    ]
  )]
)

请注意,这里的区别在于动画是根据元素是否显示而发生的。所以 ngIf 语句中的变量决定了动画是否会发生。

当您使用 [@listAnimation]="services.length" 时,据我所知,services.length 是无用的,因为您使用的是过渡方法而不是状态。我相信你想做的事情可以通过使用状态方法来完成,并根据你列表中的服务被点击来改变状态。然后切换状态,动画就会出现。你基本上已经在超时时这样做了,这就是它在某种程度上起作用的原因。因此,与其使用超时,不如使用三元运算来翻转状态,这样你就可以开始了。希望能消除一些歧义!祝你好运! :D