一、前言
动画是App体验的灵魂,流畅、统一、舒适的动效可以极大提升用户质感,也是商用项目和demo项目的最大区别之一。
很多开发者写动画只停留在“能动就行”,上线后出现大量问题:
动画卡顿、掉帧、占用主线;
页面快速跳转动画重叠、闪烁、残影;
动画无曲线、无时长,界面生硬突兀;
组件复用后动画错乱、重复执行;
页面销毁动画未终止,造成内存泄漏;
弹窗、列表、转场动效不统一,产品质感极差。
本篇系统性通关鸿蒙四大核心动画体系:属性动画、显式动画、页面转场动画、路径动画,附带全套商用模板、动画规范、性能优化与避坑方案,可直接用于企业级项目。
二、鸿蒙动画体系总览
鸿蒙ArkTS动画分为四大类,各司其职,绝对不能混用:
动画类型 | 核心API | 适用场景 | 特点 |
|---|
属性动画(隐式) | animation 属性 | 宽高、位移、透明度、缩放、圆角渐变 | 状态改变自动过渡,最简单、最高频 |
显式动画 | animateTo 函数 | 点击触发、弹窗弹出、交互反馈动画 | 手动触发、可控性强、支持回调 |
页面转场动画 | pageTransition | 页面进出、路由跳转过渡 | 全局页面切换质感提升 |
路径动画 | pathAnimation | 轨迹运动、抛物线、不规则移动 | 高阶自定义动效 |
三、属性动画(隐式动画)—— 商用最常用
属性动画核心原理:组件尺寸、位置、透明度、圆角、颜色等状态发生变化时,自动添加平滑过渡,无需手动触发。
3.1 基础通用模板
@Entry@Componentstruct AnimationPage { @State scale: number = 1 @State opacity: number = 1 @State radius: number = 10 build() { Column({ space: 30 }) { Rect() .width(200) .height(200) .borderRadius(this.radius) .scale({ x: this.scale, y: this.scale }) .opacity(this.opacity) .backgroundColor('#007DFF') // 全局属性动画配置 .animation({ duration: 300, curve: Curve.EaseInOut, delay: 0, iterations: 1, playMode: PlayMode.Normal }) Button("触发动画") .onClick(() => { this.scale = this.scale === 1 ? 0.8 : 1 this.opacity = this.opacity === 1 ? 0.5 : 1 this.radius = this.radius === 10 ? 100 : 10 }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) }}
3.2 动画参数商用规范
duration 时长:常规交互 250~300ms,弹窗 350ms,页面转场 400ms;
curve 曲线:90%场景使用 EaseInOut 自然流畅;
delay 延迟:序列动画使用,普通交互默认 0;
iterations 循环次数:普通交互单次,loading 动效无限循环。
3.3 适用场景
开关切换、面板展开收起、组件显隐、大小缩放、透明度渐变、样式状态切换。
四、显式动画 animateTo —— 精准可控交互
属性动画是“状态变了自动动”,而 animateTo 是我让它动它就动,支持动画开始、结束回调、手动精准控制,是商用弹窗、点击反馈核心方案。
4.1 基础语法与案例
@Entry@Componentstruct AnimateToPage { @State offsetY: number = 200 @State show: boolean = false build() { Column({ space: 20 }) { if (this.show) { Text("显式动画弹窗") .width(300) .height(200) .backgroundColor('#ffffff') .borderRadius(16) .offset({ y: this.offsetY }) } Button("弹出弹窗动画") .onClick(() => { animateTo({ duration: 350, curve: Curve.EaseOut, // 动画开始前 onBefore: () => { this.show = true }, // 动画结束回调 onFinish: () => { console.log("弹窗动画执行完成") } }, () => { // 动画过程中变更状态 this.offsetY = 0 }) }) Button("关闭弹窗动画") .onClick(() => { animateTo({ duration: 300 }, () => { this.offsetY = 200 }) this.show = false }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) .backgroundColor('#f5f5f5') }}
4.2 商用核心价值
五、页面转场动画 pageTransition —— 全局质感提升
原生路由跳转生硬黑屏、瞬间切换,非常廉价。通过 pageTransition 实现页面进出过渡,是商用App的标配门面。
5.1 页面入场/出场动画完整模板
@Entry@Componentstruct TransitionPage { build() { Column() { Text("带转场动画的页面") .fontSize(22) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) // 页面转场动画 .pageTransition(PageTransitionOptions .enter() .slide(SlideEffect.Right) .opacity(0, 1) .duration(400) ) .pageTransition(PageTransitionOptions .exit() .slide(SlideEffect.Left) .opacity(1, 0) .duration(300) ) }}
5.2 常用转场效果
slide 左右滑动:最通用页面跳转;
opacity 透明度渐变:弹窗、浮层页面;
scale 缩放:详情、图片预览页;
translate 位移:抽屉页面。
六、高阶路径动画 pathAnimation
用于不规则轨迹动画,比如:购物车抛物线、点赞漂浮、粒子动画、轨迹运动。
@Entry@Componentstruct PathAnimPage { @State value: number = 0 build() { Column() { Circle() .width(30) .height(30) .fillColor('#FF4444') .pathAnimation({ path: new Path() .moveTo(0, 0) .quadraticCurveTo(150, -200, 300, 0), duration: 800, iterations: -1, curve: Curve.EaseInOut }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) }}
七、商用动画落地规范(统一标准)
团队开发必须统一动画参数,避免页面质感割裂:
7.1 时长规范
按钮点击反馈:200ms
组件状态切换:250~300ms
弹窗弹出收起:350ms
页面转场:400ms
高阶轨迹动画:600~800ms
7.2 曲线规范
通用交互:EaseInOut
弹窗入场:EaseOut
退场回收:EaseIn
八、动画高频坑点与性能优化
动画循环不销毁:页面销毁无限循环动画未停止,严重内存泄漏;
多动画并发:同一组件多套动画冲突,导致闪烁抖动;
动画时长过长:页面快速点击导致动画堆叠、卡顿;
频繁状态变更触发隐式动画:列表滑动频繁刷新导致掉帧;
复杂布局做动画:嵌套过多组件动画,GPU渲染压力大;
无动画结束回调:动画未结束再次触发,状态错乱。
九、全文总结
鸿蒙动画四层体系分工明确:常规状态过渡用属性动画、交互弹窗用显式动画、页面跳转用转场动画、特殊轨迹用路径动画。
动画不是花架子,是商用App体验差异化的核心。统一的动画时长、曲线、交互反馈,能让项目从“能用”变成“好用、精致、专业”。