angular-animations
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese@angular/animations
@angular/animations
Version: Angular 21 (2025)
Tags: Animations, UI, Transitions, Motion
API Changes
API变更
This section documents recent version-specific API changes.
-
NEW: Modern animation API — Useand
animateEnterover deprecatedanimateLeave/:enter:leave -
NEW: CSS-based animations — Angular team recommends CSS for better performance
-
NEW: View transitions API — Support for browser View Transitions API
-
DEPRECATED:and
:enter— Use:leaveandanimateEnterinsteadanimateLeave
本部分记录了近期对应版本的API变动。
-
新增:现代化动画API — 推荐使用和
animateEnter替代已弃用的animateLeave/:enter:leave -
新增:基于CSS的动画 — Angular团队推荐使用CSS实现以获得更优性能
-
新增:视图过渡API — 支持浏览器原生View Transitions API
-
已弃用:和
:enter— 请使用:leave和animateEnter替代animateLeave
Best Practices
最佳实践
- Enable animations module
ts
import { provideAnimations } from '@angular/platform-browser/animations';
export const appConfig: ApplicationConfig = {
providers: [
provideAnimations()
]
};- Use triggers for state-based animations
ts
import { trigger, state, style, transition, animate } from '@angular/animations';
@Component({
animations: [
trigger('fadeInOut', [
state('hidden', style({ opacity: 0 })),
state('visible', style({ opacity: 1 })),
transition('hidden <=> visible', animate(500))
])
]
})
export class FadeComponent {
isVisible = signal(false);
}- Use enter/leave animations
ts
@Component({
animations: [
trigger('slideIn', [
transition(':enter', [
style({ transform: 'translateX(-100%)' }),
animate('300ms ease-in', style({ transform: 'translateX(0%)' }))
]),
transition(':leave', [
animate('300ms ease-out', style({ transform: 'translateX(-100%)' }))
])
])
]
})
export class SlideComponent {}- Use wildcard states for any transition
ts
trigger('expand', [
transition('* => expanded', [
style({ height: '*' }),
animate('300ms ease-out', style({ height: '200px' }))
]),
transition('expanded => *', [
animate('300ms ease-in', style({ height: '*' }))
])
])- Use query and stagger for list animations
ts
trigger('listAnimation', [
transition('* => *', [
query(':enter', [
style({ opacity: 0 }),
stagger(100, [
animate('300ms', style({ opacity: 1 }))
])
], { optional: true })
])
])- Use animation callbacks
ts
@Component({
template: `
<div [@fade]="state"
(@fade.start)="onAnimationStart()"
(@fade.done)="onAnimationDone()">
</div>
`
})
export class AnimComponent {
onAnimationStart() { console.log('Start'); }
onAnimationDone() { console.log('Done'); }
}- Use reusable triggers
ts
// animations.ts
export const fadeAnimation = trigger('fade', [
transition(':enter', [
style({ opacity: 0 }),
animate('300ms', style({ opacity: 1 }))
]),
transition(':leave', [
animate('300ms', style({ opacity: 0 }))
])
]);- Use functional animations (Angular 17+)
ts
@Component({
animations: [
trigger('expanded', [
transition(':expanded', [
animate('300ms cubic-bezier(0.4, 0, 0.2, 1)')
])
])
]
})
export class ExpandComponent {}- Optimize for performance
ts
// Prefer transform and opacity
transition('* => *', [
animate('200ms', style({
transform: 'translateX(10px)',
opacity: 0.5
}))
])
// Avoid expensive properties
// ❌ Don't animate: width, height, margin, top
// ✅ Do animate: transform, opacity- Provide reduced motion for accessibility
ts
@Component({
animations: [
trigger('slide', [
transition('* => *', [
style({ '@.disabled': '' }), // Disable for reduced motion
animate('300ms')
])
])
]
})- 启用动画模块
ts
import { provideAnimations } from '@angular/platform-browser/animations';
export const appConfig: ApplicationConfig = {
providers: [
provideAnimations()
]
};- 为基于状态的动画使用触发器
ts
import { trigger, state, style, transition, animate } from '@angular/animations';
@Component({
animations: [
trigger('fadeInOut', [
state('hidden', style({ opacity: 0 })),
state('visible', style({ opacity: 1 })),
transition('hidden <=> visible', animate(500))
])
]
})
export class FadeComponent {
isVisible = signal(false);
}- 使用进入/离开动画
ts
@Component({
animations: [
trigger('slideIn', [
transition(':enter', [
style({ transform: 'translateX(-100%)' }),
animate('300ms ease-in', style({ transform: 'translateX(0%)' }))
]),
transition(':leave', [
animate('300ms ease-out', style({ transform: 'translateX(-100%)' }))
])
])
]
})
export class SlideComponent {}- 为任意过渡使用通配符状态
ts
trigger('expand', [
transition('* => expanded', [
style({ height: '*' }),
animate('300ms ease-out', style({ height: '200px' }))
]),
transition('expanded => *', [
animate('300ms ease-in', style({ height: '*' }))
])
])- 为列表动画使用query和stagger
ts
trigger('listAnimation', [
transition('* => *', [
query(':enter', [
style({ opacity: 0 }),
stagger(100, [
animate('300ms', style({ opacity: 1 }))
])
], { optional: true })
])
])- 使用动画回调
ts
@Component({
template: `
<div [@fade]="state"
(@fade.start)="onAnimationStart()"
(@fade.done)="onAnimationDone()">
</div>
`
})
export class AnimComponent {
onAnimationStart() { console.log('Start'); }
onAnimationDone() { console.log('Done'); }
}- 使用可复用触发器
ts
// animations.ts
export const fadeAnimation = trigger('fade', [
transition(':enter', [
style({ opacity: 0 }),
animate('300ms', style({ opacity: 1 }))
]),
transition(':leave', [
animate('300ms', style({ opacity: 0 }))
])
]);- 使用函数式动画(Angular 17+)
ts
@Component({
animations: [
trigger('expanded', [
transition(':expanded', [
animate('300ms cubic-bezier(0.4, 0, 0.2, 1)')
])
])
]
})
export class ExpandComponent {}- 性能优化
ts
// 优先使用transform和opacity
transition('* => *', [
animate('200ms', style({
transform: 'translateX(10px)',
opacity: 0.5
}))
])
// 避免高开销属性
// ❌ 不要做动画的属性:width, height, margin, top
// ✅ 推荐做动画的属性:transform, opacity- 为无障碍需求提供减弱动效支持
ts
@Component({
animations: [
trigger('slide', [
transition('* => *', [
style({ '@.disabled': '' }), // 为减弱动效场景禁用动画
animate('300ms')
])
])
]
})