Angular如何延迟/交错子组件内部的动画

时间:2018-12-02 21:39:14

标签: angular angular-animations

我有一个带有动画的子组件

child.component.ts

@Component({
  selector: 'child',
  animations:[
    // animations
   ]
})
export class ChildComponent { ... }

还有一个父组件,在html中有两个子组件

parent.component.hmtl.ts

...
<child></child>
<child></child>
...

Stackblitz Example

我想要实现的是在父组件中交错子组件的动画。因此,第二个子组件应在X秒后开始动画。

animateChild()听起来可能可行,但我不知道该如何使用。那是正确的解决方案吗?如果是这样,那么举个例子真的很有帮助。

预先感谢

编辑:animateChild()在这种情况下似乎不起作用。显然,它仅适用于父组件中定义的动画。

EDIT2 :我认为通过在子组件内部的动画中添加延迟来解决问题。

child.component.ts

@Component({
  selector: 'child',
  animations:[
    animate(x),
    // animations
   ]
})
export class ChildComponent { ... }

x是一个变量,对于每个子组件都会增加。 这种解决方法对我来说有点混乱

EDIT3 :到目前为止,答案是我在第二次编辑中提到的解决方案。尽管这些方法确实有效,但我仍然将其视为解决方法。

我正在寻找仅涉及父组件的解决方案,因此子组件应保持this non working example中的样子

3 个答案:

答案 0 :(得分:3)

这些不是唯一的选择,但是我知道。兼容Angular 7。

Working Stackblitz Demo

选项1:主机绑定和状态

在子组件中,将动画状态声明为主机绑定。

@HostBinding('@animationState') animstate : string = 'preanimationstate';

然后在子组件中使用常规输入来获取延迟:

@Input('delay') delay : number;

像这样传递延迟:

<child-component [delay]="500"></child-component>

因此,现在在OnInit中,您可以使用超时:

let self = this;
window.setTimeout(function () {
    self.animstate = 'newstate';
}, self.delay);

原因:

似乎有生命的孩子也可以成为您的救赎恩典,但是这种方式也非常简单明了。希望对您有所帮助。

选项2:将动画移至HostComponent并手动应用状态

您还可以将动画定义(如果使用状态和过渡)从 child.component.ts 移到 parent.component.ts ,然后开始所有像这样的初始状态修饰符关闭子组件:

<child [@animstate]="initial"></child>>

然后通过 ViewChildren 获取元素:

@ViewChildren(ChildComponent) childComponents as QueryList<ChildComponent>;

可以通过 AfterViewInit 进行访问。使用for / each循环和window.setTimeout函数在after view init内应用状态。

答案 1 :(得分:3)

根据动画功能中的角度文档。

  

第二个参数delay的语法与duration相同。对于   例如:

     

等待100ms,然后运行200ms:“ 0.2s 100ms”

全读here

所以,我们的目标是传递第二个这样的参数

animate('2000ms {{delay}}ms'

首先,让我们将输入参数添加到您的子组件中,以便我们接受来自父组件的输入值:

export class ChildComponent implements OnInit {
  @Input() delay: number = 0;
  constructor() { }    
}

现在,让我们从父组件中传递参数值

<p>child1</p>
<app-child [delay]="0"></app-child>

<p>child2</p>
<app-child [delay]="1000"></app-child>
<p>child2 should have a delay</p>

在您的子组件中,我们需要将此参数传递给动画触发器,以便它看起来像这样

<p [@childAnimation]="{value:'',params:{delay:delay}}">
    IIIIIIIIIIIIIIIIII
</p>

最后我们可以更改动画以支持该参数值

animations: [
    trigger('childAnimation', [
      transition(':enter', [
        animate('2000ms {{delay}}ms', style({ transform: 'translateX(80%)' })),
        animate('2000ms', style({ transform: 'translateX(0)' })),
      ], { params: { delay: 0 } })
    ])
  ]

现在一切正常,您应该现在延迟输入的工作。

Check out demo here

答案 2 :(得分:0)

以防万一有人再次迷失于此问题上:如果您希望两个动画同时播放,则只需使用groupanimateChild。基本上,在第一篇文章中链接的插件中,您必须将outerTransition替换为以下内容:

const outerTransition = transition('void => *', [
  style({opacity: 0}),
  group([
    animate(2000, style({opacity: 1})),
    query('@inner', [
      animateChild()
    ]),
  ]),
]);