我有一个带有动画的子组件
child.component.ts
@Component({
selector: 'child',
animations:[
// animations
]
})
export class ChildComponent { ... }
还有一个父组件,在 html 中有 2 个子组件
parent.component.hmtl.ts
...
<child></child>
<child></child>
...
我想要实现的是在父组件中错开子组件的动画。因此第二个子组件应该在 X 秒后开始动画。
animateChild() 听起来好像它可能有用,但我不知道如何使用它。这是正确的解决方案吗?如果是这样,一个例子将非常有帮助。
提前致谢
编辑:animateChild() 似乎不适用于这种情况。显然它只适用于父组件中定义的动画。
EDIT2:我认为可能有一种解决方法,可以通过在子组件内部的动画中添加延迟来解决。
child.component.ts
@Component({
selector: 'child',
animations:[
animate(x),
// animations
]
})
export class ChildComponent { ... }
x 将是一个变量,它会随着每个子组件而增加。 这个解决方法对我来说看起来有点混乱
EDIT3:到目前为止的答案或多或少是我在第二次编辑中提到的解决方案。虽然这些确实有效,但我仍然认为它们是解决方法。
我正在寻找一种仅涉及父组件的解决方案,因此子组件应保持与这个非工作示例
中的方式相同根据动画函数中的角度文档。
第二个参数,延迟,与持续时间具有相同的语法。为了 示例:
等待100ms,然后运行200ms:'0.2s 100ms'
完整阅读这里
所以,我们的目标是传递第二个参数,如下所示
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 } })
])
]
现在一切都好,你现在应该延迟输入。
这些不是唯一的选择,但它们是我所知道的。兼容 Angular 7。
在子组件中,将动画状态声明为主机绑定。
@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);
推理:
看起来有生命的孩子也可以成为你的救星,但这种方式也非常直接和简单。希望有帮助。
您还可以将动画定义(如果使用状态和转换)从 child.component.ts 移动到 parent.component.ts,然后使用初始状态修饰符启动所有子组件,如下所示:
<child [@animstate]="initial"></child>>
然后通过 ViewChildren:
获取元素@ViewChildren(ChildComponent) childComponents as QueryList<ChildComponent>;
这可以通过 AfterViewInit 访问。使用 for/each 循环和
window.setTimeout
函数在后视图初始化中应用您的状态。
以防万一有人再次遇到这个问题:如果您希望两个动画同时播放,您只需使用
group
和 animateChild
即可。基本上,在第一篇文章中链接的 plunker 中,您必须将 outerTransition
替换为以下内容:
const outerTransition = transition('void => *', [
style({opacity: 0}),
group([
animate(2000, style({opacity: 1})),
query('@inner', [
animateChild()
]),
]),
]);
您实际上可以使用 stagger 方法和动画 query 来实现此目的:
添加此:
import { Component } from '@angular/core';
import {
trigger,
style,
animate,
query,
stagger,
transition,
} from '@angular/animations';
const transition1 = trigger('listAnimation', [
transition('* => *', [ // each time the binding value changes
query(':leave', [
stagger(-100, [
animate('0.5s', style({ opacity: 0 }))
])
], { optional: true }),
query(':enter', [
style({ opacity: 0 }),
stagger(500, [
animate('0.5s', style({ opacity: 1 }))
])
], { optional: true })
])
])
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
animations: [
transition1
]
})
export class AppComponent {
items = [];
showItems() {
this.items = [0,1,2,3,4];
}
hideItems() {
this.items = [];
}
toggle() {
this.items.length ? this.hideItems() : this.showItems();
}
}
您必须使用的唯一修改是循环出您的子组件,我本以为这就是您可能计划做的,无论如何?
如果不只是创建一个虚拟数组,其项目数量与您希望显示的子组件的数量相匹配。
注意 leave 值的负值。这实际上颠倒了项目消失的顺序。
此技术的关键是完全从父组件控制动画。
留下子组件来执行自己的动画。