从基础到实战:鸿蒙 ArkUI 属性动画开发指南
本文围绕鸿蒙属性动画展开,详解其核心原理、实现方式及项目实战技巧。属性动画是鸿蒙应用开发中最基础常用的动画类型,通过驱动组件可动画属性平滑过渡,结合视觉暂留效应呈现流畅效果。文章介绍了可动画与不可动画属性的区分,解析了duration、curve等核心参数及常见动画曲线类型,重点讲解了animation、animateTo、keyframeAnimateTo三种核心接口的用法与适配场景。结合Cat
从基础到实战:鸿蒙 ArkUI 属性动画开发指南
一、鸿蒙动画概述
在移动应用开发中,动画是提升用户体验的核心手段之一。流畅、自然的动画效果能让应用界面更具生动性和交互感,有效降低用户操作的生硬感,增强应用的易用性与吸引力。
ArkUI 提供了丰富的动画接口,核心包括属性动画、转场动画、粒子动画等,其核心原理是:驱动组件属性值按照预设的动画参数,从起始值逐步过渡到终点值。尽管属性值的变化本质上具有一定离散性,但借助人眼的视觉暂留效应,最终呈现出连续流畅的动画效果。
UI 界面的每一次更新称为一个动画帧,对应一次屏幕刷新,而帧率(FPS,Frames Per Second)是衡量动画流畅度的关键指标——帧率越高,动画越顺滑,用户视觉体验越好。
动画接口分类与作用
| 动画类型 | 作用 | 特点 |
|---|---|---|
| 属性动画 | 最基础的动画类型,由系统驱动属性逐帧变化,生成连续动画效果 | 除自定义属性动画外,应用侧无需感知动画过程 |
| 转场动画 | 为组件的出现、消失提供过渡效果 | 部分接口内置固定动画曲线,不支持开发者自定义,以保证动画一致性 |
| 粒子动画 | 实现粒子特效 | 丰富视觉效果,提升交互体验 |
| 组件动画 | 组件自带默认动效(如 List 滑动动效) | 同时部分组件支持自定义动效,降低开发成本 |
| 帧动画 | 系统提供动画过程中的插值结果,由开发者每帧修改属性值生成动画 | 支持暂停操作,但性能表现稍弱 |
在鸿蒙众多动画 API 中,属性动画是最常用、最基础的类型,也是本文的核心讲解重点。
二、鸿蒙属性动画介绍
属性接口(简称“属性”)涵盖尺寸、布局、位置、外观等多种类型,用于控制组件的显示形态与行为。对于当前界面中的组件,其部分属性(如位置、透明度)的变化会直接触发 UI 刷新,而**属性动画的作用,就是让这些属性值从起点平滑过渡到终点,避免 UI 突变带来的生硬感**。
可动画属性与不可动画属性
根据属性变化是否适合添加动画,可将其分为**可动画属性与不可动画属性**:
可动画属性
| 分类 | 说明 |
|---|---|
| 布局属性 | 位置、大小、内边距、外边距、对齐方式、权重等,直接影响组件在界面中的布局形态 |
| 仿射变换 | 平移、旋转、缩放、锚点等,用于实现组件的空间变换效果 |
| 背景 | 背景颜色、背景模糊等,影响组件的背景呈现效果 |
| 内容 | 文字大小、文字颜色,图片对齐方式、模糊效果等,与组件内部内容的显示相关 |
| 前景 | 前景颜色等,覆盖在组件内容之上的视觉效果 |
| Overlay | Overlay 相关属性,用于实现组件的叠加显示效果 |
| 外观 | 透明度、圆角、边框、阴影等,直接影响组件的视觉外观 |
| 其他 | 其他系统支持的可动画属性,根据具体版本及组件特性有所扩展 |
不可动画属性
zIndex(层级)、focusable(焦点控制)、enabled(交互开关)等,这类属性变化不适合添加动画,需立即生效。
核心概念
- 属性动画:通过改变组件的可动画属性值实现动画效果,是鸿蒙系统中最基础、最常用的动画类型,无需开发者手动控制每帧变化。
- 动画参数:控制动画播放的核心配置,包括动画持续时间、曲线类型、重复次数、播放模式、延迟时间等。
- 动画曲线:定义属性值变化的速度规律,直接决定动画的“运动质感”,如匀速、缓入缓出、弹簧振动等。
- 动画状态:动画生命周期中的不同阶段,包括开始、进行中、暂停、结束等,开发者可根据需求监听状态变化。
核心动画参数详解
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| duration | number | 动画持续时间,单位为毫秒(ms),决定动画从开始到结束的耗时 | - |
| curve | Curve | 动画曲线,定义属性值变化的速度规律,是决定动画质感的核心参数 | Curve.Linear(线性) |
| delay | number | 动画延迟时间,单位为毫秒(ms),即触发动画后,延迟多久开始播放 | 0 |
| iterations | number | 动画重复次数,取值为正整数,-1 表示无限循环播放 | 1 |
| playMode | PlayMode | 动画播放模式,包括正向(Normal)、反向(Reverse)、交替(Alternate)等,控制动画重复播放时的方向 | PlayMode.Normal |
常见动画曲线类型
| 曲线类型 | 说明 | 适用场景 |
|---|---|---|
| Curve.Linear | 线性动画,属性值匀速变化,速度保持不变 | 简单的平移、旋转,需要匀速运动的场景 |
| Curve.Ease | 缓入缓出动画,开始和结束时速度较慢,中间速度较快,过渡自然 | 大部分通用场景,如组件显示/隐藏、按钮点击反馈 |
| Curve.EaseIn | 缓入动画,开始时速度较慢,逐渐加快 | 组件入场、从远到近的运动效果 |
| Curve.EaseOut | 缓出动画,开始时速度较快,逐渐减慢 | 组件退场、从近到远的运动效果 |
| Curve.EaseInOut | 缓入缓出动画,与 Ease 效果类似,过渡更细腻 | 需要细腻过渡的场景,如弹窗动画、卡片切换 |
| Curve.Friction | 摩擦动画,模拟物体受到摩擦力逐渐减速的效果,自然收尾 | 拖拽后的回弹、物体落地的缓冲效果 |
| Curve.Spring | 弹簧动画,模拟弹簧振动的效果,带有轻微回弹 | 需要弹性反馈的场景,如按钮点击、组件回弹 |
三、鸿蒙属性动画的实现方式
属性动画的核心是通过动画接口驱动组件属性变化,ArkUI 提供了三种核心动画接口——animation、animateTo、keyframeAnimateTo,分别适用于不同场景,可灵活实现各类属性动画效果。
| 动画接口 | 作用域 | 原理 | 使用场景 |
|---|---|---|---|
| animation | 组件通过属性接口绑定的属性变化 | 自动识别组件的可动画属性变化,为其添加动画;组件接口调用自上而下执行,animation 仅作用于其上方的属性调用,支持为多个属性设置不同动画参数 | 对多个可动画属性配置不同动画参数的场景,需为单个组件的不同属性设置差异化动画 |
| animateTo | 闭包内改变属性引起的界面变化 | 通用函数,对比闭包执行前与闭包内状态变量引起的 UI 差异,为差异部分添加动画;支持多次调用、嵌套使用,闭包内所有属性变化遵循相同动画参数 | 对多个可动画属性配置相同动画参数的场景,需要嵌套动画的场景;多段动画循环可通过 playMode 和 iterations 实现 |
| keyframeAnimateTo | 多个闭包内改变属性引起的分段属性动画 | 通用函数,每一段闭包中的状态变量与前一次状态的差异,单独生成一段动画;支持多次调用,不推荐嵌套,每段动画可单独配置参数 | 同一属性需要实现连续多个动画的场景,避免多次创建动画导致的衔接卡顿 |
1. 基本属性动画(animation)
animation 是最简洁的属性动画实现方式,直接在组件上设置 animation 属性,即可为组件的可动画属性变化添加动画效果,无需额外复杂配置,适合简单场景的快速实现。
核心步骤:声明状态变量 → 将状态变量绑定到组件可动画属性 → 设置 animation 动画参数 → 触发状态变量变化,触发动画。
import { curves } from '@kit.ArkUI';
@Entry
@Component
struct AttrAnimationDemo3 {
@State animate: boolean = false;
// 第一步: 声明相关状态变量,绑定组件可动画属性
@State rotateValue: number = 0; // 组件一旋转角度
@State translateX: number = 0; // 组件二水平偏移量
@State opacityValue: number = 1; // 组件透明度
// 第二步:将状态变量绑定到组件的可动画属性上
build() {
Row() {
// 组件一:旋转+透明度动画
Column() {
}
.opacity(this.opacityValue)
.rotate({ angle: this.rotateValue })
// 第三步:设置animation属性,配置动画参数
.animation({ curve: curves.springMotion() })
.backgroundColor('#317AF7')
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.borderRadius(30)
.onClick(() => {
this.animate = !this.animate;
// 第四步:修改状态变量,触发属性变化,进而触发动画
this.rotateValue = this.animate ? 90 : 0; // 旋转动画
this.translateX = this.animate ? 50 : 0; // 组件二偏移动画
this.opacityValue = this.animate ? 0.6 : 1; // 透明度动画
})
// 组件二:平移+透明度动画
Column() {
}
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.backgroundColor('#D94838')
.borderRadius(30)
.opacity(this.opacityValue)
.translate({ x: this.translateX })
.animation({ curve: curves.springMotion() })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
说明:点击组件一后,状态变量发生变化,组件一的 rotate 属性、组件二的 translate 和 opacity 属性随之变化,animation 接口自动为这些属性变化添加弹簧动画,实现平滑过渡。
2. 显式动画(animateTo)
animateTo 是显式动画接口,通过传入动画参数和闭包函数,闭包内所有属性变化将遵循统一的动画参数,适合需要为多个组件、多个属性设置相同动画效果的场景,支持嵌套使用,灵活性更高。
接口定义:
animateTo(value: AnimateParam, event: () => void): void
参数说明:value 为动画参数配置(AnimateParam 对象),event 为闭包函数,闭包内的状态变量变化所引发的 UI 差异,将自动应用该动画参数。
import { curves } from '@kit.ArkUI';
@Entry
@Component
struct AttrAnimateToDemo2 {
@State animate: boolean = false;
// 第一步: 声明相关状态变量
@State rotateValue: number = 0; // 组件一旋转角度
@State translateX: number = 0; // 组件二水平偏移量
@State opacityValue: number = 1; // 组件透明度
// 第二步:将状态变量绑定到组件可动画属性
build() {
Row() {
// 组件一
Column() {
}
.rotate({ angle: this.rotateValue })
.backgroundColor('#317AF7')
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.borderRadius(30)
.onClick(() => {
// 第三步:调用animateTo接口,配置动画参数和闭包
this.getUIContext()?.animateTo({ curve: curves.springMotion() }, () => {
this.animate = !this.animate;
// 闭包内修改状态变量,所有属性变化遵循相同动画参数
this.rotateValue = this.animate ? 90 : 0; // 组件一旋转
this.opacityValue = this.animate ? 0.6 : 1; // 组件二透明度
this.translateX = this.animate ? 50 : 0; // 组件二平移
})
})
// 组件二
Column() {
}
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.backgroundColor('#D94838')
.borderRadius(30)
.opacity(this.opacityValue)
.translate({ x: this.translateX })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
说明:与 animation 接口不同,animateTo 将动画参数统一配置在接口中,闭包内所有属性变化(旋转、平移、透明度)均使用相同的弹簧曲线,无需为每个组件单独设置 animation,适合批量控制动画效果。
3. 关键帧动画(keyframeAnimateTo)
keyframeAnimateTo 用于实现分段动画,通过传入整体动画参数和关键帧数组,每一段关键帧可单独配置时长、曲线等参数,适合同一属性需要连续执行多个动画的场景,避免多次创建动画导致的衔接卡顿。
接口定义:
keyframeAnimateTo(param: KeyframeAnimateParam, keyframes: Array<KeyframeState>): void
参数说明:param 为关键帧动画整体参数(如重复次数、延迟、结束回调);keyframes 为关键帧数组,每一项包含当前关键帧的时长、曲线、闭包事件(属性变化逻辑)。
@Entry
@Component
struct KeyframeAnimateToDemo {
// 第一步: 声明相关状态变量
@State rotateValue: number = 0; // 组件一旋转角度
@State translateX: number = 0; // 组件二水平偏移量
@State opacityValue: number = 1; // 组件透明度
// 第二步:将状态变量绑定到组件可动画属性
build() {
Row() {
// 组件一
Column() {
}
.rotate({ angle: this.rotateValue })
.backgroundColor('#317AF7')
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.borderRadius(30)
.onClick(() => {
// 第三步:调用keyframeAnimateTo接口,配置整体参数和关键帧数组
this.getUIContext()?.keyframeAnimateTo({
iterations: 1 // 整体动画重复次数
}, [
{
// 第一段关键帧:800ms,弹簧曲线,属性变化
duration: 800,
curve: curves.springMotion(),
event: () => {
this.rotateValue = 90; // 组件一顺时针旋转90度
this.opacityValue = 0.6; // 组件二透明度降低
this.translateX = 50; // 组件二向右偏移50px
}
},
{
// 第二段关键帧:500ms,缓出曲线,属性恢复
duration: 500,
curve: Curve.EaseOut,
event: () => {
this.rotateValue = 0; // 组件一恢复初始角度
this.opacityValue = 1; // 组件二透明度恢复
this.translateX = 0; // 组件二恢复初始位置
}
}
]);
})
// 组件二
Column() {
}
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.backgroundColor('#D94838')
.borderRadius(30)
.opacity(this.opacityValue)
.translate({ x: this.translateX })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
说明:点击组件一后,将依次执行两段关键帧动画:第一段 800ms 实现组件旋转、偏移和透明度变化,第二段 500ms 实现属性恢复,两段动画衔接自然,无卡顿,适合需要多阶段动画的场景(如复杂的组件交互反馈)。


四、项目实战:喵屿应用中的属性动画
喵屿是一款宠物管理类应用,为提升用户体验,应用中广泛运用属性动画,实现了生动的交互效果和视觉反馈。以下结合具体代码示例,讲解属性动画在实际项目中的落地方式、优化策略及最终效果。
1. 应用中的动画实现
喵屿应用的动画设计遵循“简洁、自然、贴合场景”的原则,重点运用 animation 和 animateTo 接口,实现了主页面猫咪交互、设置页面列表入场等核心动画效果。
1.1 主页面猫咪交互动画
主页面的猫咪头像为核心交互元素,点击后实现“躲起-随机出现”的动画效果,增强应用的趣味性,采用 animation 接口实现,结合定时器控制属性变化时序。
代码实现(MainPage.ets):
Image($r(`[resource].media.${this.curPet}`))
.width(70)
.height(100)
.objectFit(ImageFit.Cover)
.draggable(false) // 禁止图片手势拖动(默认值为true)
.visibility(this.showPet ? Visibility.Visible : Visibility.None)
// 绑定位置属性,控制猫咪的x、y坐标
.position({ x: this.catX, y: this.windowHeight - this.listHeight - this.catOffsetY })
// 配置动画参数,实现自然过渡
.animation({
duration: 800, // 动画持续800ms,过渡流畅
curve: Curve.Friction, // 摩擦曲线,模拟自然减速效果
iterations: 1, // 仅播放一次
playMode: PlayMode.Normal // 正向播放
})
.clickEffect({ level: ClickEffectLevel.HEAVY, scale: 0.9 }) // 点击反馈效果
.onClick(() => {
VibrateUtil.buttonVibrate(VibrateEffect.soft); // 结合震动反馈,增强交互感
// 第一步:猫咪“躲起”(y坐标上移)
this.catOffsetY = -100;
// 随机生成猫咪出现的x坐标
this.randomCatX();
// 第二步:1s后猫咪随机位置出现(y坐标下移)
setTimeout(() => {
this.catOffsetY = 50 + Math.random() * 30;
}, 1000);
// 第三步:1.5s后猫咪恢复初始高度
setTimeout(() => {
this.catOffsetY = 37;
}, 1500);
})
效果说明:点击猫咪头像后,猫咪先向下“躲起”(y坐标偏移量变为-100),1秒后在随机x坐标位置向下出现(y坐标偏移量随机在50~80之间),1.5秒后恢复初始高度;动画采用摩擦曲线,过渡自然不突兀,结合震动反馈,提升用户交互体验。
1.2 设置页面列表入场动画
设置页面的列表项采用“顺序入场”动画,通过为不同列表项设置不同的动画延迟,实现层次感和流动感,提升页面加载时的视觉体验,采用 animation 接口实现。
代码实现(Settings.ets):
ListItem() {
this.listItem(item); // 列表项内容组件
}
.padding({ left: 16, right: 16 })
.width(CommonConstants.FULL_SIZE)
// 绑定透明度和偏移量属性,控制入场效果
.opacity(this.isShow ? 1 : 0)
.translate({ x: this.isShow ? 0 : 100 })
// 配置入场动画参数,设置延迟实现顺序效果
.animation({
duration: 500, // 动画持续500ms
delay: index * 50, // 每一项延迟50ms入场,形成顺序效果
curve: Curve.EaseOut // 缓出曲线,入场更自然
})
效果说明:页面加载时,isShow 状态变为 true,列表项从右侧(x偏移100px)、透明(opacity=0)状态,逐步过渡到正常状态;由于每一项的动画延迟为 index*50ms,列表项将按顺序依次入场,形成流畅的流动感,避免所有列表项同时入场的生硬感。
注:入场动画建议使用转场动画实现,此处实现仅为作为对比,详情见主页《从基础到实战:鸿蒙 ArkUI 转场动画开发指南》
2. 动画优化策略
在实际项目开发中,动画的流畅性直接影响用户体验,若动画卡顿、延迟,会降低应用的专业度。喵屿应用在属性动画开发中,结合鸿蒙系统特性,采用了以下优化策略,兼顾动画效果与性能。
核心优化策略
-
合理设置动画时长:根据动画场景的复杂度,设置适配的时长——简单交互(如按钮点击)设置 300~500ms,复杂动画(如猫咪交互)设置 600~800ms,避免过长导致等待感,过短导致过渡突兀。
-
精准选择动画曲线:结合场景选择合适的曲线,如猫咪交互用 Curve.Friction 模拟自然减速,列表入场用 Curve.EaseOut 实现平滑过渡,弹性反馈用 Curve.Spring,让动画更贴合真实物理规律,提升自然感。
-
避免过度动画:核心交互场景(如点击、页面切换)使用动画增强反馈,非核心场景(如普通文本刷新)不添加动画,避免视觉疲劳和性能消耗。
-
巧用动画延迟:在列表、网格等多元素场景中,为不同元素设置递增的动画延迟,创造层次感和流动感,同时避免多元素同时动画导致的性能压力。
-
结合震动反馈:动画触发时,搭配轻微的震动反馈(如猫咪点击、按钮点击),增强用户的触觉交互,让动画反馈更立体。
-
优先选择低开销属性:组件位置、大小变化(如 translate、scale)中,scale 属性不会触发布局测量,性能开销远低于 layout 相关属性;在组件大小、位置连续变化的场景(如跟手交互),优先使用 scale 替代 layout 属性,提升动画流畅度。
-
区分动画类型场景:属性动画仅作用于“始终存在”的组件;组件出现、消失的动画,应使用转场动画,避免属性动画导致的卡顿或异常。
-
谨慎使用动画结束回调:属性动画由系统驱动,无需开发者手动处理结束逻辑;若必须使用结束回调,需妥善处理连续操作的数据管理,避免时序错乱。
-
适配系统场景:当系统开发者选项中关闭过渡动画,或 UIAbility 从前台切换至后台时,动画会立即执行结束回调;需对这类场景进行验证,避免在结束回调中加入时序相关的核心逻辑(如页面跳转、数据请求)。
五、总结
鸿蒙属性动画是基于组件属性变化实现的基础动画类型,也是鸿蒙应用开发中最常用的动画方式,其核心优势在于:
- 简单易用:通过声明式的方式定义动画效果,代码简洁易读
- 功能丰富:支持多种动画参数和曲线类型,可以实现各种复杂的动画效果
- 性能优秀:鸿蒙系统对属性动画进行了优化,保证了动画的流畅性和性能
核心要点总结
-
**属性动画的核心**是“驱动可动画属性平滑过渡”,需先区分可动画属性与不可动画属性,避免无效动画配置。
-
三种核心动画接口(animation、animateTo、keyframeAnimateTo)各有适配场景,需根据“是否需要统一参数”“是否需要分段动画”灵活选择。
-
动画参数(尤其是曲线)的选择是关键,需结合场景贴合真实物理规律,让动画更自然。
-
实战开发中,需兼顾动画效果与性能,通过选择低开销属性、避免过度动画、适配系统场景等策略,保证动画流畅稳定。
属性动画并非孤立存在,在实际开发中,可与转场动画、粒子动画等结合使用,实现更复杂的动画效果。希望通过本文的讲解,开发者能够全面掌握鸿蒙属性动画的开发技巧,将其灵活运用到自身项目中,打造出既美观又实用、既流畅又高效的鸿蒙应用,为用户提供更优质的交互体验。
动画效果欢迎下载应用体验: 喵屿下载链接
更多推荐




所有评论(0)