本指南详细介绍了鸿蒙应用中实现丝滑动画的完整方案包含动画演示、核心 API、工具类封装和性能优化策略。目录动画场景演示动画系统架构动画工具类实现性能优化策略最佳实践建议动画场景演示以下是项目中实现的各类动画效果每个场景都包含效果演示和完整实现代码。场景 1APP 冷启动动画效果演示应用启动时的转场动画效果实现代码// 列表项依次出现形成瀑布流效果 List() { ForEach(this.configList, (item: ConfigData, index: number) { ListItem() { // 列表项内容 Row() { Image(item.icon).width(40).height(40) Text(item.title).fontSize(16) } } .transition(customAnimationUtil.isScaleTran(index, this.uiConfig)) }) }核心 API// 转场缩放动画工具方法 public isScaleTran(i: number, uiConfig: UIConfig) { return uiConfig.isAnimation ? TransitionEffect.OPACITY .combine(TransitionEffect.scale({x: 0, y: 0})) .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i * 10 30 // 递增延迟 }) : null }关键要点动画类型转场缩放动画 (TransitionEffect)动画曲线弹性曲线curves.springMotion()延迟策略index * 10 30毫秒实现瀑布流效果适用场景列表项加载、配置项显示、卡片展示场景 2列表项缩放动画效果演示列表项依次从小到大出现实现代码// 配置列表项动画 List() { ForEach(this.settingsList, (item: SettingItem, index: number) { ListItem() { Row() { SymbolGlyph(item.icon) .fontSize(24) .effectStrategy(customAnimationUtil.isIconEffect(this.uiConfig)) Column() { Text(item.title).fontSize(16) Text(item.subtitle).fontSize(12).fontColor(Color.Gray) } } .padding(16) } .transition(customAnimationUtil.isScaleTran(index, this.uiConfig)) .clickEffect(customAnimationUtil.isClickEffect(this.uiConfig)) }) }核心 API// 组合使用转场动画、点击动效和图标动效 .transition(customAnimationUtil.isScaleTran(index, this.uiConfig)) .clickEffect(customAnimationUtil.isClickEffect(this.uiConfig)) .effectStrategy(customAnimationUtil.isIconEffect(this.uiConfig))关键要点动画组合转场 点击 图标三重动效用户反馈点击时缩放到 95%提供触觉反馈图标动效系统图标的内置缩放效果适用场景设置列表、功能菜单、选项卡场景 3卡片展开动画效果演示卡片点击后平滑展开或收起实现代码// 卡片展开/收起动画 ForEach(this.cardList, (card: CardData, i: number) { Column() { // 卡片头部 Row() { Text(card.title).fontSize(18) Image($r(sys.symbol.chevron_down)) .rotate({ angle: this.theCurrentHomeCard[i] ? 180 : 0 }) .animation({ duration: this.uiConfig.animationSpeed, curve: curves.springMotion() }) } // 卡片内容可展开 if (this.theCurrentHomeCard[i]) { Column() { Text(card.content) } .transition(customAnimationUtil.isScaleTran(0, this.uiConfig)) } } .onClick(() { animateTo({ duration: this.uiConfig.animationSpeed, curve: curves.springMotion() }, () { this.theCurrentHomeCard.splice(i, 1, !this.theCurrentHomeCard[i]) }) }) })核心 API// 使用 animateTo 包裹状态变化 animateTo({ duration: this.uiConfig.animationSpeed, curve: curves.springMotion() }, () { this.theCurrentHomeCard.splice(i, 1, !this.theCurrentHomeCard[i]) })关键要点动画类型显式动画 (animateTo)状态管理使用splice触发响应式更新图标旋转箭头图标旋转 180 度指示展开状态适用场景折叠面板、FAQ 列表、详情展开场景 4按钮状态切换动画效果演示圆形按钮展开为胶囊按钮实现代码// 按钮状态切换动画 Component struct AnimatedButton { Prop Switch: boolean Prop Icon1: Resource Prop Icon2: Resource Prop SubText: string StorageLink(uiConfig) uiConfig: UIConfig new UIConfig() build() { Column() { Row() { SymbolGlyph(this.Switch ? this.Icon1 : this.Icon2) .fontSize(24) .effectStrategy(customAnimationUtil.isIconEffect(this.uiConfig)) Text(this.SubText) .fontSize(20) .fontColor(this.Switch ? Color.White : Color.Transparent) .opacity(this.Switch ? 1 : 0) } .padding({ left: 16, right: 16 }) } .width(this.Switch ? $r(app.integer.vp_proxy_started_button_width) : // 展开宽度 120 $r(app.integer.vp_proxy_not_start_button_width) // 收缩宽度 56 ) .height($r(app.integer.vp_proxy_not_start_button_height)) // 56 .backgroundColor(this.Switch ? Color.Blue : Color.Gray) .borderRadius(28) .animation({ duration: this.uiConfig.animationSpeed, curve: curves.springMotion() }) .transition(customAnimationUtil.isSlideSwitch(this.uiConfig)) .clickEffect(customAnimationUtil.isClickEffect(this.uiConfig)) } }核心 API// 宽度属性动画 .width(this.Switch ? 120 : 56) .animation({ duration: this.uiConfig.animationSpeed, curve: curves.springMotion() }) // 非对称转场动画 .transition(customAnimationUtil.isSlideSwitch(this.uiConfig))关键要点动画类型属性动画 非对称转场宽度变化圆形 (56x56) ↔ 胶囊 (120x56)文本淡入透明度从 0 到 1适用场景开关按钮、状态指示器、计时器场景 5点击动效效果演示点击时组件缩小反馈实现代码// 为所有可点击元素添加点击动效 Button(确认) .clickEffect(customAnimationUtil.isClickEffect(this.uiConfig)) .onClick(() { // 处理点击事件 }) // 自定义组件也可以使用 Row() { Image($r(app.media.icon)).width(40) Text(选项).fontSize(16) } .clickEffect(customAnimationUtil.isClickEffect(this.uiConfig)) .onClick(() { // 处理点击事件 })核心 API// 点击动效工具方法 public isClickEffect(uiConfig: UIConfig) { return uiConfig.isAnimation ? { level: ClickEffectLevel.MIDDLE, // 中等强度 scale: 0.95 // 缩放到 95% } : null } // 使用 .clickEffect(customAnimationUtil.isClickEffect(this.uiConfig))关键要点动画类型交互动效 (ClickEffect)缩放级别LIGHT (0.9) / MIDDLE (0.95) / HEAVY (0.8)自动恢复松开后自动恢复原始大小适用场景所有可点击元素按钮、卡片、列表项场景 6标签页切换动画效果演示标签页图标缩放 指示器平移实现代码// 底部标签栏动画 Component struct TabBar { State tabsIconScale: number 1 State tabsSelect: TabsSelect new TabsSelect() StorageLink(uiConfig) uiConfig: UIConfig new UIConfig() private SwiperController: SwiperController new SwiperController() build() { Column() { // Swiper 内容区 Swiper(this.SwiperController) { ForEach(this.tabsList, (tab: TabData) { // 页面内容 Text(tab.content) }) } .indicator(false) .loop(false) .duration(this.uiConfig.animationSpeed) .curve(Curve.EaseInOut) .onChange((index: number) { animateTo({ duration: this.uiConfig.animationSpeed, curve: curves.interpolatingSpring(10, 1, 228, 30), }, () { this.tabsSelect.swiperPage index this.switchTranslateX(index) }) }) // 底部标签栏 Row() { ForEach(this.tabsList, (tab: TabData, i: number) { Column() { SymbolGlyph(tab.icon) .fontSize(24) .fontColor(this.tabsSelect.swiperPage tab.page ? Color.Blue : Color.Gray) .scale(this.tabsSelect.swiperPage tab.page ? {x: this.tabsIconScale, y: this.tabsIconScale} : {x: 1, y: 1} ) .effectStrategy(customAnimationUtil.isIconEffect(this.uiConfig)) Text(tab.title) .fontSize(12) .fontColor(this.tabsSelect.swiperPage tab.page ? Color.Blue : Color.Gray) } .onTouch((event: TouchEvent) { animateTo({ duration: this.uiConfig.animationSpeed, curve: Curve.Ease, }, () { if (event.type TouchType.Down) { this.switchTranslateX(i) this.tabsSelect.swiperPage tab.page this.tabsIconScale 0.8 // 按下缩小 this.SwiperController.changeIndex(i, true) } else if (event.type TouchType.Up) { this.tabsIconScale 1 // 松开恢复 } }) }) }) } .transition(customAnimationUtil.isTranslate(this.uiConfig)) } } switchTranslateX(index: number) { // 计算指示器位置 } }核心 API// 触摸事件控制缩放 .onTouch((event: TouchEvent) { animateTo({ duration: this.uiConfig.animationSpeed, curve: Curve.Ease, }, () { if (event.type TouchType.Down) { this.tabsIconScale 0.8 // 按下 } else if (event.type TouchType.Up) { this.tabsIconScale 1 // 松开 } }) }) // Swiper 切换同步动画 .onChange((index: number) { animateTo({ duration: this.uiConfig.animationSpeed, curve: curves.interpolatingSpring(10, 1, 228, 30), }, () { this.tabsSelect.swiperPage index }) })关键要点动画类型触摸反馈 Swiper 联动图标缩放按下 0.8松开 1.0插值弹簧interpolatingSpring(10, 1, 228, 30)实现平滑过渡适用场景底部导航栏、顶部标签页、分段控制器场景 7Swiper 切换动画效果演示页面滑动切换效果实现代码// Swiper 页面切换动画 Component struct ProxyGroupSwiper { State currentProxyIndex: number 0 StorageLink(uiConfig) uiConfig: UIConfig new UIConfig() private SwiperController: SwiperController new SwiperController() private ListScroller: Scroller new Scroller() build() { Column() { // 顶部指示器列表 List({ scroller: this.ListScroller }) { ForEach(this.theProxyGroups, (group: ProxyGroup, index: number) { ListItem() { Text(group.name) .fontSize(16) .fontColor(this.currentProxyIndex index ? Color.Blue : Color.Gray) .onClick(() { animateTo({ duration: this.uiConfig.animationSpeed }, () { this.currentProxyIndex index }) this.SwiperController.changeIndex( index, this.uiConfig.animationSpeed ! 0 ? true : false ) }) } }) } .listDirection(Axis.Horizontal) // Swiper 内容区 Swiper(this.SwiperController) { ForEach(this.theProxyGroups, (group: ProxyGroup) { // 页面内容 ProxyGroupContent({ group: group }) }) } .indicator(false) .loop(false) .duration(this.uiConfig.animationSpeed) .curve(Curve.EaseInOut) .onGestureSwipe((index: number, extraInfo: SwiperAnimationEvent) { animateTo({ duration: this.uiConfig.animationSpeed }, () { // 处理手势滑动逻辑 }) }) .onAnimationStart((index: number, targetIndex: number) { animateTo({ duration: this.uiConfig.animationSpeed }, () { this.ListScroller.scrollToIndex(targetIndex) this.currentProxyIndex targetIndex }) }) } } }核心 API// Swiper 配置 Swiper(this.SwiperController) { } .duration(this.uiConfig.animationSpeed) // 动画时长 .curve(Curve.EaseInOut) // 缓动曲线 .onGestureSwipe() // 手势滑动回调 .onAnimationStart() // 动画开始回调 // 编程式切换 this.SwiperController.changeIndex(index, true)关键要点动画类型手势动画 显式动画双向同步Swiper ↔ 指示器列表手势支持滑动切换 点击切换适用场景轮播图、引导页、多页表单场景 8滑动转场动画效果演示页面从左到右滑入效果实现代码// 页面滑动转场动画 Entry Component struct PageTransition { State isShow: boolean false StorageLink(uiConfig) uiConfig: UIConfig new UIConfig() build() { Navigation() { Column() { Button(打开新页面) .onClick(() { this.isShow true }) } } .mode(NavigationMode.Stack) // 新页面 if (this.isShow) { Column() { Row() { Image($r(sys.symbol.chevron_left)) .onClick(() { this.isShow false }) Text(新页面).fontSize(18) } // 页面内容 List() { ForEach(this.contentList, (item: ContentData, index: number) { ListItem() { Text(item.title) } .transition(customAnimationUtil.isSlide(index * 10, this.uiConfig)) }) } } .width(100%) .height(100%) .backgroundColor(Color.White) .transition(customAnimationUtil.isSlide(0, this.uiConfig)) } } }核心 API// 左滑入动画 public isSlide(i: number, uiConfig: UIConfig) { return uiConfig.isAnimation ? TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i }) .combine(TransitionEffect.SLIDE) : null } // 右滑入动画 public isSlideR(i: number, uiConfig: UIConfig) { return uiConfig.isAnimation ? TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i }) .combine(TransitionEffect.translate({x: 20})) : null }关键要点动画类型转场滑动动画 (TransitionEffect.SLIDE)方向支持左滑入、右滑入、上滑入、下滑入配合透明度滑动 淡入效果更自然适用场景页面跳转、侧边栏、抽屉菜单场景 9旋转动画效果演示无限循环旋转效果实现代码// 加载旋转动画 Component struct LoadingSpinner { State rotateAngle: number 0 StorageLink(uiConfig) uiConfig: UIConfig new UIConfig() aboutToAppear() { this.startAnim() } startAnim() { this.rotateAngle 0 animateTo({ duration: this.uiConfig.animationSpeed, curve: Curve.Linear, iterations: -1, // 无限循环 playMode: PlayMode.Normal }, () { this.rotateAngle 360 }) } stopAnim() { animateTo({ duration: 0 }, () { this.rotateAngle 0 }) } build() { Column() { Image($r(app.media.loading_icon)) .width(40) .height(40) .rotate({ angle: this.uiConfig.isAnimation ? this.rotateAngle : 0 }) } } } // 刷新按钮旋转动画 Component struct RefreshButton { State rotateAngle: number 0 StorageLink(uiConfig) uiConfig: UIConfig new UIConfig() build() { Image($r(sys.symbol.arrow_clockwise)) .width(24) .height(24) .rotate({ angle: this.rotateAngle }) .onClick(() { animateTo({ duration: this.uiConfig.animationSpeed, curve: Curve.EaseOut, }, () { this.rotateAngle 360 }) // 执行刷新操作 this.refresh() }) } refresh() { // 刷新逻辑 } }核心 API// 无限循环旋转 animateTo({ duration: 300, curve: Curve.Linear, iterations: -1, // -1 表示无限循环 playMode: PlayMode.Normal }, () { this.rotateAngle 360 }) // 单次旋转 animateTo({ duration: 300, curve: Curve.EaseOut, }, () { this.rotateAngle 360 }) // 应用旋转 .rotate({ angle: this.rotateAngle })关键要点动画类型属性动画 (rotate)循环模式Normal (正向) / Alternate (往返)曲线选择Linear (匀速) / EaseOut (缓出)适用场景加载指示器、刷新按钮、进度动画动画系统架构1. 统一动画管理项目采用集中式动画管理方案通过Animation.ets工具类统一管理所有动画效果// entry/src/main/ets/common/utils/Animation.ets class AnimationUtil { // 转场缩放动画 public isScaleTran(i: number, uiConfig: UIConfig) { } // 转场滑动动画 public isSlide(i: number, uiConfig: UIConfig) { } // 点击动效 public isClickEffect(uiConfig: UIConfig) { } // 图标动效 public isIconEffect(uiConfig: UIConfig) { } } export const customAnimationUtil new AnimationUtil()2. 动画配置系统通过UIConfig类实现全局动画配置export class UIConfig { // 动画开关 isAnimation: boolean true // 动画速度毫秒 animationSpeed: number 300 // 动画速度档位索引 animationSpeedIndex: number 1 // 0:快速, 1:正常, 2:慢速, 3:关闭 // 震动反馈 isVibrate: boolean true // 按钮位置索引影响按钮动画方向 buttonPositionIndex: number 0 } // 动画速度映射 const ANIMATION_SPEEDS [150, 300, 500, 0] // 快速、正常、慢速、关闭3. 核心动画类型3.1 转场动画 (TransitionEffect)用于组件出现和消失时的过渡效果缩放转场TransitionEffect.scale({x: 0, y: 0})滑动转场TransitionEffect.SLIDE透明度转场TransitionEffect.OPACITY平移转场TransitionEffect.translate({x: 20})非对称转场TransitionEffect.asymmetric(进入, 退出)3.2 显式动画 (animateTo)用于状态变化时的平滑过渡animateTo({ duration: 300, curve: curves.springMotion() }, () { // 状态变化 this.value newValue })3.3 属性动画直接在属性上添加.animation()修饰符.width(this.isExpanded ? 200 : 100) .animation({ duration: 300, curve: curves.springMotion() })3.4 交互动效点击动效.clickEffect()悬停效果.hoverEffect()图标动效.effectStrategy()动画工具类实现完整工具类代码import { UIConfig } from ../../entryability/AppState import { curves } from kit.ArkUI let effectEvent: TransitionEffect | null let clickEffect: ClickEffect | null let iconEffect: SymbolEffectStrategy | null class AnimationUtil { // 1. 转场缩放动画标准延迟 public isScaleTran(i: number, uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.OPACITY .combine(TransitionEffect.scale({x: 0, y: 0})) .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i * 10 30 }) : null return effectEvent } // 2. 转场缩放动画快速延迟 public isScaleTranFast(i: number, uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.OPACITY .combine(TransitionEffect.scale({x: 0, y: 0})) .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i * 5 30 }) : null return effectEvent } // 3. 转场透明度动画 public isOpacity(uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: Curve.Ease, delay: 0 }) : null return effectEvent } // 4. 转场滑动动画左到右 public isSlide(i: number, uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i }) .combine(TransitionEffect.SLIDE) : null return effectEvent } // 5. 转场滑动动画右到左 public isSlideR(i: number, uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i }) .combine(TransitionEffect.translate({x: 20})) : null return effectEvent } // 6. 转场放大动画 public isSlideScaleBig(i: number, uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i }) .combine(TransitionEffect.scale({x: 0, y: 0})) : null return effectEvent } // 7. 转场缩小动画非对称 public isSlideScaleSmall(i: number, uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.asymmetric( TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i }) .combine(TransitionEffect.scale({x: 2, y: 2})), TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i }) .combine(TransitionEffect.translate({y: -5})) ) : null return effectEvent } // 8. 按钮滑动切换动画 public isSlideSwitch(uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? (uiConfig.buttonPositionIndex 0 ? TransitionEffect.asymmetric( TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: 50 }) .combine(TransitionEffect.SLIDE_SWITCH), TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: 50 }) .combine(TransitionEffect.SLIDE) ) : uiConfig.buttonPositionIndex 2 ? TransitionEffect.asymmetric( TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: 50 }) .combine(TransitionEffect.SLIDE), TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: 50 }) .combine(TransitionEffect.SLIDE_SWITCH) ) : TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: 50 }) .combine(TransitionEffect.SLIDE_SWITCH)) : null return effectEvent } // 9. 底部标签栏转场动画 public isTranslate(uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.OPACITY .animation({ duration: uiConfig.animationSpeed, delay: 0 }) .combine(TransitionEffect.translate({ y: 50 })) : null return effectEvent } // 10. 点击动效 public isClickEffect(uiConfig: UIConfig) { clickEffect uiConfig.isAnimation ? { level: ClickEffectLevel.MIDDLE, scale: 0.95 } : null return clickEffect } // 11. 图标动效 public isIconEffect(uiConfig: UIConfig) { iconEffect uiConfig.isAnimation ? SymbolEffectStrategy.SCALE : null return iconEffect } // 12. 图标转场缩放旋转动画 public isScaleTranIcon(i: number, uiConfig: UIConfig) { effectEvent uiConfig.isAnimation ? TransitionEffect.scale({x: 0, y: 0}) .combine(TransitionEffect.rotate({angle: 360})) .animation({ duration: uiConfig.animationSpeed, curve: curves.springMotion(), delay: i * 10 50 }) : null return effectEvent } } export const customAnimationUtil new AnimationUtil()使用方法// 1. 导入工具类 import { customAnimationUtil } from ../common/utils/Animation // 2. 获取配置 StorageLink(uiConfig) uiConfig: UIConfig new UIConfig() // 3. 使用动画 .transition(customAnimationUtil.isScaleTran(index, this.uiConfig)) .clickEffect(customAnimationUtil.isClickEffect(this.uiConfig)) .effectStrategy(customAnimationUtil.isIconEffect(this.uiConfig))性能优化策略1. 动画开关控制实现方案通过全局配置控制动画开关export class UIConfig { isAnimation: boolean true // 动画总开关 animationSpeed: number 300 // 动画速度 animationSpeedIndex: number 1 // 速度档位 } // 动画速度映射 const ANIMATION_SPEEDS [150, 300, 500, 0] // 快速、正常、慢速、关闭优势用户可根据设备性能选择动画档位低端设备可关闭动画提升流畅度节省电量2. 条件性应用动画实现方案根据配置决定是否应用动画.transition( uiConfig.isAnimation ? customAnimationUtil.isScaleTran(index, uiConfig) : null )优势避免不必要的动画计算减少渲染负担3. 延迟优化标准延迟适用于普通列表delay: i * 10 30 // 每项延迟10ms快速延迟适用于大量元素delay: i * 5 30 // 每项延迟5ms固定延迟适用于单个元素delay: 50 // 固定延迟4. 动画曲线选择弹性曲线 (springMotion)适用于大部分场景curve: curves.springMotion()自然的弹性效果符合物理运动规律用户体验最佳线性曲线 (Linear)适用于循环动画curve: Curve.Linear匀速运动适合旋转、进度条等缓动曲线 (Ease)适用于简单过渡curve: Curve.Ease先加速后减速适合透明度、位移等插值弹簧曲线适用于精细控制curve: curves.interpolatingSpring(10, 1, 228, 30)参数速度、阻尼、质量、初始速度可精确控制弹性效果5. 避免过度动画问题同时触发过多动画导致卡顿解决方案限制同时播放的动画数量使用虚拟滚动减少渲染元素大列表使用快速延迟模式// 使用快速延迟 .transition(customAnimationUtil.isScaleTranFast(index, this.uiConfig)) // 限制最大延迟 .transition(customAnimationUtil.isScaleTran( Math.min(index, 10), // 限制最大延迟 this.uiConfig ))6. 动画状态管理问题频繁切换动画状态导致性能问题解决方案使用标志位控制动画触发export class isON { toggleAnim: boolean false // 动画触发标志 } // 使用 .transition(this.isON.toggleAnim ? null : customAnimationUtil.isScaleTran(index, this.uiConfig))7. 性能监控// 使用 HiTrace 监控动画性能 import { hiTraceMeter } from kit.PerformanceAnalysisKit hiTraceMeter.startTrace(animation_performance, 1) animateTo({ duration: 300 }, () { // 动画逻辑 }) hiTraceMeter.finishTrace(animation_performance, 1)最佳实践建议1. 动画设计原则1.1 一致性原则同类型交互使用相同动画效果统一动画时长和曲线保持视觉语言一致1.2 性能优先原则优先使用 GPU 加速的属性transform、opacity避免动画 width、height 等触发重排的属性使用scale代替width/height动画1.3 用户体验原则动画时长控制在 200-400ms提供动画开关选项避免过度动画干扰用户操作2. 代码组织建议2.1 集中管理动画配置// 统一的动画工具类 export const customAnimationUtil new AnimationUtil() // 统一的配置类 StorageLink(uiConfig) uiConfig: UIConfig new UIConfig()2.2 使用语义化命名// 好的命名 isScaleTran() // 缩放转场 isSlideSwitch() // 滑动切换 isClickEffect() // 点击效果 // 避免 anim1() effect() trans()2.3 注释说明动画效果// 转场缩放动画i为延迟在list或foreach中可以将i设为index达到递增的动画效果 public isScaleTran(i: number, uiConfig: UIConfig) { // 实现代码 }3. 常见动画组合3.1 列表项出现动画TransitionEffect.OPACITY .combine(TransitionEffect.scale({x: 0, y: 0})) .animation({ duration: 300, curve: curves.springMotion(), delay: index * 10 30 })3.2 页面切换动画TransitionEffect.asymmetric( TransitionEffect.move(TransitionEdge.END), TransitionEffect.move(TransitionEdge.START) ) .animation({ duration: 300, curve: Curve.Ease }) .combine(TransitionEffect.OPACITY)3.3 按钮交互动画// 点击缩放 .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.95 }) // 悬停效果 .hoverEffect(HoverEffect.Scale) // 图标动效 .effectStrategy(SymbolEffectStrategy.SCALE)4. 动画调试技巧4.1 动画速度调试// 开发时使用慢速动画便于观察 const DEBUG_MODE true const animationSpeed DEBUG_MODE ? 1000 : 3004.2 动画开关调试// 快速切换动画开关测试性能 StorageLink(uiConfig) uiConfig: UIConfig new UIConfig() // 在设置页提供开关 Toggle({ type: ToggleType.Switch, isOn: this.uiConfig.isAnimation }) .onChange((isOn: boolean) { this.uiConfig.isAnimation isOn })4.3 日志输出animateTo({ duration: this.uiConfig.animationSpeed, onFinish: () { console.info(动画完成) } }, () { console.info(动画开始) this.currentIndex targetIndex })5. 避免动画卡顿问题场景大量元素同时动画复杂布局计算频繁状态更新解决方案// 1. 分批动画 ForEach(this.list, (item, index) { ListItem() { } .transition(customAnimationUtil.isScaleTran( Math.min(index, 10), // 限制最大延迟 this.uiConfig )) }) // 2. 使用 LazyForEach LazyForEach(this.dataSource, (item, index) { ListItem() { } .transition(customAnimationUtil.isScaleTranFast(index, this.uiConfig)) }) // 3. 条件性渲染 if (this.isVisible) { Component() .transition(customAnimationUtil.isOpacity(this.uiConfig)) }动画效果速查表动画类型方法名适用场景延迟参数曲线缩放转场isScaleTran()列表项、卡片index * 10 30springMotion快速缩放转场isScaleTranFast()大量元素index * 5 30springMotion透明度转场isOpacity()简单显隐0Ease左滑入isSlide()页面切换固定值springMotion右滑入isSlideR()侧边栏固定值springMotion放大转场isSlideScaleBig()强调元素固定值springMotion缩小转场isSlideScaleSmall()删除动画0springMotion按钮切换isSlideSwitch()按钮状态50springMotion底部栏isTranslate()标签栏0Ease点击效果isClickEffect()所有可点击元素--图标效果isIconEffect()系统图标--图标转场isScaleTranIcon()设置项图标index * 10 50springMotion动画曲线对比曲线类型特点适用场景代码springMotion弹性效果大部分场景curves.springMotion()Linear匀速运动循环动画Curve.LinearEase缓入缓出简单过渡Curve.EaseEaseIn缓入元素消失Curve.EaseInEaseOut缓出元素出现Curve.EaseOutEaseInOut缓入缓出页面切换Curve.EaseInOutinterpolatingSpring自定义弹簧精细控制curves.interpolatingSpring(10, 1, 228, 30)总结核心要点统一管理使用工具类集中管理所有动画效果性能优先提供动画开关支持多档速度用户体验使用弹性曲线控制合理时长代码复用封装通用动画减少重复代码灵活配置支持全局配置和局部定制实现步骤创建Animation.ets工具类定义UIConfig配置类在组件中引入并使用提供用户设置界面测试和优化性能推荐配置// 推荐的动画配置 export class UIConfig { isAnimation: boolean true // 默认开启 animationSpeed: number 300 // 300ms 最佳 animationSpeedIndex: number 1 // 正常速度 } // 推荐的动画曲线 curve: curves.springMotion() // 弹性效果最佳 // 推荐的延迟策略 delay: index * 10 30 // 标准列表 delay: index * 5 30 // 大量元素 delay: 50 // 单个元素参考资源HarmonyOS 动画官方文档TransitionEffect APIanimateTo APIcurves 曲线库