Angular 如何 delay/stagger 子组件内部的动画
Angular how to delay/stagger the animation inside of child components
我有一个带有动画的子组件
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: 到目前为止的答案或多或少是我在第二次编辑中提到的解决方案。虽然这些确实有效,但我仍然认为它们是解决方法。
我正在寻找一个只涉及父组件的解决方案,因此子组件应该保持它在 this non working example
中的样子
这些不是唯一的选择,但它们是我所知道的。 Angular 7兼容。
选项 1:主机绑定和状态
在您的 child 组件中,将您的动画状态声明为 host-binding。
@HostBinding('@animationState') animstate : string = 'preanimationstate';
然后在您的 child 组件中使用正常输入来获得延迟:
@Input('delay') delay : number;
像这样传递延迟:
<child-component [delay]="500"></child-component>
所以现在在 OnInit 中你可以只使用超时:
let self = this;
window.setTimeout(function () {
self.animstate = 'newstate';
}, self.delay);
推理:
动画 child 似乎也可以成为您的救星,但这种方式也非常直接和简单。希望对你有帮助。
选项 2:将动画移动到 HostComponent 并手动应用状态
您还可以将动画定义(如果它使用状态和转换)从 child.component.ts 移动到 parent.component.ts,然后用这样的初始状态修饰符启动所有 child 组件:
<child [@animstate]="initial"></child>>
然后通过 ViewChildren 获取元素:
@ViewChildren(ChildComponent) childComponents as QueryList<ChildComponent>;
这可以通过 AfterViewInit 访问。使用 for/each 循环和 window.setTimeout
函数在后视图初始化中应用您的状态。
以防万一有人再次遇到这个问题:如果您希望同时播放两个动画,您只需使用 group
和 animateChild
。基本上,在第一个 post 中链接的 plunker 中,您必须将 outerTransition
替换为以下内容:
const outerTransition = transition('void => *', [
style({opacity: 0}),
group([
animate(2000, style({opacity: 1})),
query('@inner', [
animateChild()
]),
]),
]);
根据动画功能中的 angular 文档。
The second argument, delay, has the same syntax as duration. For
example:
Wait for 100ms and then run for 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 } })
])
]
现在一切都好,你现在应该延迟输入。
我有一个带有动画的子组件
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: 到目前为止的答案或多或少是我在第二次编辑中提到的解决方案。虽然这些确实有效,但我仍然认为它们是解决方法。
我正在寻找一个只涉及父组件的解决方案,因此子组件应该保持它在 this non working example
中的样子这些不是唯一的选择,但它们是我所知道的。 Angular 7兼容。
选项 1:主机绑定和状态
在您的 child 组件中,将您的动画状态声明为 host-binding。
@HostBinding('@animationState') animstate : string = 'preanimationstate';
然后在您的 child 组件中使用正常输入来获得延迟:
@Input('delay') delay : number;
像这样传递延迟:
<child-component [delay]="500"></child-component>
所以现在在 OnInit 中你可以只使用超时:
let self = this;
window.setTimeout(function () {
self.animstate = 'newstate';
}, self.delay);
推理:
动画 child 似乎也可以成为您的救星,但这种方式也非常直接和简单。希望对你有帮助。
选项 2:将动画移动到 HostComponent 并手动应用状态
您还可以将动画定义(如果它使用状态和转换)从 child.component.ts 移动到 parent.component.ts,然后用这样的初始状态修饰符启动所有 child 组件:
<child [@animstate]="initial"></child>>
然后通过 ViewChildren 获取元素:
@ViewChildren(ChildComponent) childComponents as QueryList<ChildComponent>;
这可以通过 AfterViewInit 访问。使用 for/each 循环和 window.setTimeout
函数在后视图初始化中应用您的状态。
以防万一有人再次遇到这个问题:如果您希望同时播放两个动画,您只需使用 group
和 animateChild
。基本上,在第一个 post 中链接的 plunker 中,您必须将 outerTransition
替换为以下内容:
const outerTransition = transition('void => *', [
style({opacity: 0}),
group([
animate(2000, style({opacity: 1})),
query('@inner', [
animateChild()
]),
]),
]);
根据动画功能中的 angular 文档。
The second argument, delay, has the same syntax as duration. For example:
Wait for 100ms and then run for 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 } })
])
]
现在一切都好,你现在应该延迟输入。