鸿蒙 使用动画 简单使用
动画就两个,属性动画和转场动画
属性动画只是组件的属性发生变化,而转场动画是指对将要出现或消失的组件做动画,而文档的其他动画只是给这两个动画效果锦上添花罢了
这篇文章简单介绍这两个动画,其他的看文档去吧
属性动画
以下是三种 ArkUI 属性动画接口的对比表格,用通俗语言解释它们的核心差异:
对比维度 | animateTo | animation | keyframeAnimateTo |
---|---|---|---|
功能定位 | 打包式动画(集体行动) | 贴标签式动画(各自为战) | 里程碑式动画(分阶段闯关) |
典型场景 | 多个属性同步变化(如按钮点击缩放+变色) | 不同属性独立动画(如颜色渐变 1 秒,缩放 0.5 秒) | 复杂多阶段动画(如加载进度条分段变速) |
代码结构 | 包裹在闭包内的属性集合 | 链式附加在属性后 | 定义关键帧数组 + 全局参数 |
动画控制 | 统一时长/曲线 | 每个属性独立设置参数 | 每个阶段独立设置时长/曲线 |
阶段数量 | 单一阶段 | 单一阶段 | 多阶段(通过数组定义多个关键帧) |
曲线独立性 | 全局统一曲线 | 属性独立曲线 | 阶段独立曲线 |
延迟/循环控制 | 仅支持全局延迟 | 无内置延迟/循环 | 支持全局延迟、循环次数(含无限循环) |
嵌套能力 | 支持多层嵌套动画 | 不支持嵌套 | 可与其他动画组合使用 |
性能优化建议 | 优先用transform 代替布局属性 | 同左 | 避免频繁改变布局属性 |
通俗类比 | 交响乐团(统一指挥) | 独奏演员(各自演奏) | 电影分镜(按剧本分段表演) |
一句话选择指南
- 想让多个属性整齐划一变化 →
animateTo
- 想让不同属性各玩各的 →
animation
- 需要分步骤、变速的复杂动画 →
keyframeAnimateTo
animateTo
animateTo(value: AnimateParam, event: () => void): void
- value 指定 AnimateParam 对象(包括时长、Curve 等)
- event 为动画的闭包函数
示例:点击后一个从左向右滚 90° 的方块且颜色变半透明
import { curves } from '@kit.ArkUI';@Entry
@Component
struct AnimateToDemo {@State animate: boolean = false;// 第一步: 声明相关状态变量@State rotateValue: number = 0; // 旋转角度@State translateX: number = 0; // 偏移量@State opacityValue: number = 1; // 透明度// 第二步:将状态变量设置到相关可动画属性接口build() {Row() {Column() {}.width(100).height(100).backgroundColor('#D94838').borderRadius(30).opacity(this.opacityValue).translate({ x: this.translateX }).rotate({ angle: this.rotateValue })}.onClick(() => {// 直接使用animateTo可能导致实例不明确的问题,建议使用getUIContext获取UIContext实例// 第三步:调用 keyframeAnimateTo 接口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;})})}
}
animation
把 animation 接口加在要做属性动画的可动画属性后即可
示例:点击后一个从左向右滚 90° 的方块且颜色变半透明
import { curves } from '@kit.ArkUI';@Entry
@Component
struct AnimationDemo {@State animate: boolean = false;// 第一步: 声明相关状态变量@State rotateValue: number = 0; // 旋转角度@State translateX: number = 0; // 偏移量@State opacityValue: number = 1; // 透明度// 第二步:将状态变量设置到相关可动画属性接口build() {Row() {Column() {}.width(100).height(100).backgroundColor('#D94838').borderRadius(30).opacity(this.opacityValue).translate({ x: this.translateX })// 第三步:通过属性动画接口开启属性动画.rotate({ angle: this.rotateValue }).animation({ curve: curves.springMotion() })// 这里和animateTo的不同,直接加.onClick(() => {this.animate = !this.animate;// 第四步:闭包内通过状态变量改变UI界面// 这里可以写任何能改变UI的逻辑比如数组添加,显隐控制,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画// 组件一的rotate属性发生变化,所以会给组件一添加rotate旋转动画this.rotateValue = this.animate ? 90 : 0;// 组件二的translate属性发生变化,所以会给组件二添加translate偏移动画this.translateX = this.animate ? 50 : 0;// 父组件column的opacity属性有变化,会导致其子节点的透明度也变化,所以这里会给column和其子节点的透明度属性都加动画this.opacityValue = this.animate ? 0.6 : 1;})}}
}
keyframeAnimateTo
keyframeAnimateTo(param: KeyframeAnimateParam, keyframes: Array<KeyframeState>): void
keyframeAnimateTo 接口参数中,第一个参数 KeyframeAnimateParam 为关键帧动画的整体参数(包括延时、播放次数、结束回调、期望帧率),第二个参数是一个数组,每一项表示一个关键帧内的动画行为;每一段动画可单独控制动画参数(包括时长、Curve 等)。
示例:点击后一个从左向右滚 90° 的方块且颜色变半透明,又滚回去且无限循环
@Entry
@Component
struct KeyframeAnimateToDemo {// 第一步: 声明相关状态变量@State rotateValue: number = 0; // 逆时针旋转90度恢复至0度@State translateX: number = 0; // 偏移量@State opacityValue: number = 1; // 透明度// 第二步:将状态变量设置到相关可动画属性接口build() {Row() {Column() {}.width(100).height(100).backgroundColor('#D94838').borderRadius(30).opacity(this.opacityValue).translate({ x: this.translateX }).rotate({ angle: this.rotateValue }).onClick(() => {this.getUIContext()?.keyframeAnimateTo({iterations: -1, // 无限循环}, [{// 第一段关键帧动画时长为800ms,顺时针旋转90度,透明度变从1变为0.6,translate从0位移到50duration: 800,event: () => {this.rotateValue = 90;this.opacityValue = 0.6;this.translateX = 50;}},{// 第二段关键帧动画时长为500ms,逆时针旋转90度恢复至0度,透明度变从0.6变为1,translate从50位移到0duration: 500,event: () => {this.rotateValue = 0;this.opacityValue = 1;this.translateX = 0;}}]);})}}
}
转场动画
文档太他妈多了,我就说下面这个吧
出现/消失转场:对新增、消失的控件实现动画效果
- transition 是基础的组件转场接口,用于实现一个组件出现或者消失时的动画效果
- 可以通过 TransitionEffect 对象的组合使用,定义出各式效果。
分三步写:
- 创建 TransitionEffect
- 将转场效果通过 transition 接口设置到组件
- 新增或者删除组件触发转场
示例:点击边框后组件跑了,组件跑的姿势很多
import { curves } from '@kit.ArkUI';@Entry
@Component
struct TransitionEffectDemo {@State isPresent: boolean = false;// 第一步,创建 TransitionEffectprivate effect: TransitionEffect =// 创建默认透明度转场效果,并指定了springMotion(0.6, 0.8)曲线TransitionEffect.OPACITY.animation({curve: curves.springMotion(0.6, 0.8)})// 通过combine方法,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion(0.6, 0.8).combine(TransitionEffect.scale({x: 0,y: 0}))// 添加旋转转场效果,这里的动画参数会跟随上面带animation的TransitionEffect,也就是springMotion(0.6, 0.8).combine(TransitionEffect.rotate({ angle: 90 }))// 添加平移转场效果,这里的动画参数使用指定的springMotion().combine(TransitionEffect.translate({ y: 150 }).animation({ curve: curves.springMotion() }))// 添加move转场效果,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion().combine(TransitionEffect.move(TransitionEdge.END));build() {Stack() {if (this.isPresent) {Column() {Text('ArkUI').fontWeight(FontWeight.Bold).fontSize(20).fontColor(Color.White)}.justifyContent(FlexAlign.Center).width(150).height(150).borderRadius(10).backgroundColor(0xf56c6c)// 第二步:将转场效果通过transition接口设置到组件.transition(this.effect)}// 边框Column().width(155).height(155).border({width: 5,radius: 10,color: Color.Black})}// 第三步:新增或者删除组件触发转场,控制新增或者删除组件.onClick(() => {this.isPresent = !this.isPresent;})}
}