Skip to content

动画系统

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 的参数

参数类型说明
durationnumber动画时长(ms)
curveCurve动画曲线
fillModeFillMode填充模式(None/Forwards/Backwards/Both)
delaynumber延迟时间
iterationCountnumber迭代次数
onFinishfunction动画完成回调
onStopfunction动画停止回调
onProgressfunction进度回调

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 沿路径"