Angular路由组件推送in/out动画
Angular routing component push in/out animation
我正在尝试为组件设置动画以“将自身推入” 和“被推出”视图。目前,单个容器元素承载一个组件,该组件占据 100% space.
动画将触发第二个组件(位于路由器出口内)将自己从右侧推入,并与 space 共享 50% 的 space第一个组件(收缩时需要有流畅的动画)。
反之亦然,退出动画看起来像是第一个组件“推动”第二个组件离开视野。
下面是这个场景的模板文件(假设组件文件中已经正确导入了动画)
<div class="container">
<div class="component-1"
[@triggerComponent1]="outlet.isActivated ? 'shrink' : 'stretch'">
<component-1></component-1>
</div>
<div class="component-2 col-6"
[@triggerComponent2]="outlet.isActivated ? 'open' : 'close'">
<router-outlet #outlet="outlet"></router-outlet>
</div>
</div>
下面是各自的动画触发函数
export const animation1 = trigger('triggerComponent1', [
state('stretch', style({
flex: '0 0 auto',
width: '100%'
})),
state('shrink', style({
flex: '0 0 auto',
width: '50%'
})),
transition('* => stretch', animate('400ms cubic-bezier(0.35, 0, 0.25, 1)')
),
transition('* => shrink', animate('400ms cubic-bezier(0.35, 0, 0.25, 1)'))
]);
export const animation2 = trigger('triggerComponent2', [
state('open', style({
transform: 'translateX(0%)'
})),
state('close', style({
transform: 'translateX(100%)'
})),
transition('* => open', animate('400ms cubic-bezier(0.35, 0, 0.25, 1)')
),
transition('* => close', animate('400ms cubic-bezier(0.35, 0, 0.25, 1)'))
]);
这种方法的问题是动画不是并行发生的。组件 1 将平滑收缩,将白色 space 暴露在其 右侧 。然后,当 slide 动画完成时,组件 2 就“出现”了。
理想情况下,我需要将动画与 group()
相结合,但我不确定如何编写触发器,也不确定如何将其包含在模板中。
这是给你的堆栈闪电战
https://stackblitz.com/edit/expanding-drawer-animation?file=src/app/animations.ts
我是这样做的。
<div class="container">
<div class="component-1">
<div class="content">
<button (click)="toggle()">expand</button>
<h1>{{ isExpanded }}</h1>
</div>
</div>
<div class="component-2" [@slideIn]="isExpanded ? 'open' : 'close'">
<div class="content">
<h1>Bender?! You stole the atom.</h1>
</div>
</div>
</div>
然后一些 CSS.
.container {
width: 100%;
max-width: 100%;
background: red;
display: flex;
flex-direction: row;
}
.content {
padding: 10px;
}
.component-1 {
flex: 1;
background: rgb(161, 161, 255);
}
.component-2 {
flex: 1;
background: green;
max-width: 50%;
overflow: hidden;
}
parent 是一个 div flex,而 2 children 是 50 / 50 flex:1。然后你可以溢出隐藏右边的div并根据变量设置max-width为50%:0。我们将使用它来触发动画。
import {
animate,
state,
style,
transition,
trigger,
} from '@angular/animations';
export class Animations {
static page = [
trigger('slideIn', [
state('close', style({ maxWidth: '0%', visibility: 'hidden' })),
state('open', style({ maxWidth: '50%', visibility: 'visible' })),
transition('close <=> open', [animate('.6s ease-in-out')]),
transition(':enter', [
style({ opacity: 1 }),
animate('.6s 1.2s ease-in-out'),
]),
]),
];
}
希望对您有所帮助!
我还在 stackblitz 中为您做了第二个,使用绝对位置并使用填充滑动超过 50%,就像我在下面的评论中所说的那样。
我正在尝试为组件设置动画以“将自身推入” 和“被推出”视图。目前,单个容器元素承载一个组件,该组件占据 100% space.
动画将触发第二个组件(位于路由器出口内)将自己从右侧推入,并与 space 共享 50% 的 space第一个组件(收缩时需要有流畅的动画)。
反之亦然,退出动画看起来像是第一个组件“推动”第二个组件离开视野。
下面是这个场景的模板文件(假设组件文件中已经正确导入了动画)
<div class="container">
<div class="component-1"
[@triggerComponent1]="outlet.isActivated ? 'shrink' : 'stretch'">
<component-1></component-1>
</div>
<div class="component-2 col-6"
[@triggerComponent2]="outlet.isActivated ? 'open' : 'close'">
<router-outlet #outlet="outlet"></router-outlet>
</div>
</div>
下面是各自的动画触发函数
export const animation1 = trigger('triggerComponent1', [
state('stretch', style({
flex: '0 0 auto',
width: '100%'
})),
state('shrink', style({
flex: '0 0 auto',
width: '50%'
})),
transition('* => stretch', animate('400ms cubic-bezier(0.35, 0, 0.25, 1)')
),
transition('* => shrink', animate('400ms cubic-bezier(0.35, 0, 0.25, 1)'))
]);
export const animation2 = trigger('triggerComponent2', [
state('open', style({
transform: 'translateX(0%)'
})),
state('close', style({
transform: 'translateX(100%)'
})),
transition('* => open', animate('400ms cubic-bezier(0.35, 0, 0.25, 1)')
),
transition('* => close', animate('400ms cubic-bezier(0.35, 0, 0.25, 1)'))
]);
这种方法的问题是动画不是并行发生的。组件 1 将平滑收缩,将白色 space 暴露在其 右侧 。然后,当 slide 动画完成时,组件 2 就“出现”了。
理想情况下,我需要将动画与 group()
相结合,但我不确定如何编写触发器,也不确定如何将其包含在模板中。
这是给你的堆栈闪电战
https://stackblitz.com/edit/expanding-drawer-animation?file=src/app/animations.ts
我是这样做的。
<div class="container">
<div class="component-1">
<div class="content">
<button (click)="toggle()">expand</button>
<h1>{{ isExpanded }}</h1>
</div>
</div>
<div class="component-2" [@slideIn]="isExpanded ? 'open' : 'close'">
<div class="content">
<h1>Bender?! You stole the atom.</h1>
</div>
</div>
</div>
然后一些 CSS.
.container {
width: 100%;
max-width: 100%;
background: red;
display: flex;
flex-direction: row;
}
.content {
padding: 10px;
}
.component-1 {
flex: 1;
background: rgb(161, 161, 255);
}
.component-2 {
flex: 1;
background: green;
max-width: 50%;
overflow: hidden;
}
parent 是一个 div flex,而 2 children 是 50 / 50 flex:1。然后你可以溢出隐藏右边的div并根据变量设置max-width为50%:0。我们将使用它来触发动画。
import {
animate,
state,
style,
transition,
trigger,
} from '@angular/animations';
export class Animations {
static page = [
trigger('slideIn', [
state('close', style({ maxWidth: '0%', visibility: 'hidden' })),
state('open', style({ maxWidth: '50%', visibility: 'visible' })),
transition('close <=> open', [animate('.6s ease-in-out')]),
transition(':enter', [
style({ opacity: 1 }),
animate('.6s 1.2s ease-in-out'),
]),
]),
];
}
希望对您有所帮助!
我还在 stackblitz 中为您做了第二个,使用绝对位置并使用填充滑动超过 50%,就像我在下面的评论中所说的那样。