Appearance
动画系统
ArkUI 提供 4 种动画类型,各有适用场景。
1. 四种动画类型总览
| 动画类型 | 装饰器 | 适用场景 | 特点 |
|---|---|---|---|
| 属性动画 | .animation() | 单属性变化 | 最常用 |
| 显式动画 | .animateTo() | 复杂多属性 | 精确控制 |
| 转场动画 | .transition() | 组件显隐 | if/else / Visibility |
| 路径动画 | .motionPath() | 沿路径移动 | 复杂轨迹 |
2. 属性动画(@Builder 装饰的 animation)
2.1 基本用法
typescript
@Component
struct AnimatedButton {
@State isExpanded: boolean = false
@State scaleValue: number = 1
build() {
Button(this.isExpanded ? '展开' : '收起')
.scale({
x: this.scaleValue,
y: this.scaleValue
})
.onClick(() => {
this.isExpanded = !this.isExpanded
this.scaleValue = this.isExpanded ? 1.2 : 1
})
// 动画配置
.animation({
duration: 300,
curve: Curve.EaseInOut,
playMode: PlayMode.Normal // Normal/Once/Alternate
})
}
}2.2 曲线(Curve)类型
| 曲线 | 效果 |
|---|---|
Curve.Linear | 匀速 |
Curve.Ease | 慢进慢出(默认) |
Curve.EaseIn | 慢进 |
Curve.EaseOut | 慢出 |
Curve.EaseInOut | 慢进慢出 |
Curve.BackIn | 回退进入 |
Curve.BackOut | 回退退出 |
Curve.BackInOut | 回退进和出 |
3. 显式动画(animateTo)
3.1 基本用法
typescript
@Component
struct AnimatedCard {
@State width: number = 100
@State height: number = 100
@State radius: number = 0
@State rotation: number = 0
build() {
Column() {
Button('动画')
.onClick(() => {
animateTo({
duration: 500,
curve: Curve.EaseInOut,
onFinish: () => console.log('动画完成')
}, () => {
this.width = 200
this.height = 200
this.radius = 50
this.rotation = 360
})
})
Text('内容')
.width(this.width)
.height(this.height)
.borderRadius(this.radius)
.rotate({ angle: this.rotation })
}
}
}3.2 animateTo 的参数
| 参数 | 类型 | 说明 |
|---|---|---|
duration | number | 动画时长(ms) |
curve | Curve | 动画曲线 |
fillMode | FillMode | 填充模式(None/Forwards/Backwards/Both) |
delay | number | 延迟时间 |
iterationCount | number | 迭代次数 |
onFinish | function | 动画完成回调 |
onStop | function | 动画停止回调 |
onProgress | function | 进度回调 |
4. 转场动画(transition)
4.1 基本用法
typescript
@Entry
@Component
struct Index {
@State showCard: boolean = false
build() {
Column() {
Button('切换')
.onClick(() => {
this.showCard = !this.showCard
})
if (this.showCard) {
// 进入动画 + 退出动画
Card()
.transition({
type: TransitionType.OPACITY, // 透明度
// 进入参数
enterTransition: TransitionEffect.translate({ x: 0, y: 100 }).opacity(),
// 退出参数
exitTransition: TransitionEffect.translate({ x: 0, y: -100 }).opacity(),
// 组合动画
duration: 300
})
} else {
Text('卡片隐藏')
}
}
}
}4.2 组合转场效果
typescript
// 进入:平移 + 缩放 + 旋转 + 淡入
.enterTransition(
TransitionEffect.translate({ x: 100, y: 0 }).scale({ x: 0.5, y: 0.5 }).rotate({ angle: 180 }).opacity()
)
// 退出:平移 + 缩放 + 淡出
.exitTransition(
TransitionEffect.translate({ x: -100, y: 0 }).scale({ x: 0.5, y: 0.5 }).opacity()
)4.3 支持的过渡效果
| 效果 | 说明 |
|---|---|
opacity() | 透明度 |
translate({x, y, z}) | 平移 |
scale({x, y, z}) | 缩放 |
rotate({angle}) | 旋转 |
blur(radius) | 模糊 |
combiner() | 组合 |
5. 路径动画(motionPath)
5.1 基本用法
typescript
@Component
struct MotionPathDemo {
@State progress: number = 0
aboutToAppear() {
// 自动播放
animateTo({ duration: 3000, curve: Curve.Linear }, () => {
this.progress = 1
})
}
build() {
Column() {
Circle({ width: 20, height: 20 })
.fill(Color.Red)
.motionPath({
path: 'M 0 0 L 300 0 L 300 300 L 0 300 Z', // 路径
progress: this.progress // 进度 0-1
})
}
.width('100%')
.height('100%')
}
}6. 动效中断
6.1 什么是动效中断
当动画正在执行时,用户产生新的手势操作,动画系统采用"弹簧模型"平滑过渡到新状态,而不是生硬跳变。
typescript
@Component
struct InterruptDemo {
@State offsetX: number = 0
// 动画执行中 → 用户再次点击 → 平滑过渡到新位置
build() {
Text('拖动我')
.offset({ x: this.offsetX, y: 0 })
.animation({
duration: 300,
curve: Curve.EaseInOut
})
.onTouch((event: TouchEvent) => {
switch (event.type) {
case TouchType.Down:
// 动画会自动中断并重新计算
break
case TouchType.Move:
this.offsetX = event.touches[0].x - 100
break
}
return true
})
}
}7. 面试高频考点
Q1: 四种动画类型分别是什么?
回答:
- 属性动画(.animation):单属性变化,最常用
- 显式动画(.animateTo):多属性组合,精确控制
- 转场动画(.transition):组件显隐的进入/退出动画
- 路径动画(.motionPath):沿指定路径移动
Q2: 什么是动效中断?
回答:动画执行中用户产生新手势,系统采用弹簧模型平滑过渡到新状态,而不是生硬跳变。提供更自然的交互体验。
Q3: TransitionEffect 的组合使用?
回答:可以组合 translate + scale + opacity + rotate,用 .opacity() 等方式串联多个效果。
🐱 小猫提示:动画部分记住 "属性动画最常用、animateTo 最灵活、transition 用于显隐、motionPath 沿路径"。