HarmonyOS 关键帧动画 keyframeAnimateTo

news/2025/11/27 13:04:22/文章来源:https://www.cnblogs.com/xiaokangzhao/p/19277084

使用UI上下文API中的.keyframeAnimateTo()方法创建关键帧动画,其中传两个参数,第一个参 数是个对象,此对象有三个参数delay、iterations、onFinish;第二个参数是数组,其中是一个个对象,每个对象都是一个关键帧

基础使用

@Entry
@Component
struct Index {@State scaleXY:number = 1build() {Text().width(100).height(100).backgroundColor(Color.Red).scale({ x: this.scaleXY, y: this.scaleXY })    // 1. who ✅.onClick(() => {// 设置关键帧动画整体播放3次   2. fixed 💕this.getUIContext().keyframeAnimateTo({ iterations: 3 }, [{// 第一段关键帧动画时长为800ms,scale属性做从1到1.5的动画duration: 800,event: () => {this.scaleXY = 1.5;}},{// 第二段关键帧动画时长为500ms,scale属性做从1.5到1的动画duration: 500,event: () => {this.scaleXY = 1;}}])})}
}

实战案例1:图片点击按下效果

@Entry
@Component
struct Index {@State scaleXY: number = 1@State selectIndex:number = -1@State imgSrc: string[] = ['https://tse2-mm.cn.bing.net/th/id/OIP-C.CFev6LAEXxvcqAH9BkJvMwHaNK?rs=1&pid=ImgDetMain','https://pic2.zhimg.com/v2-379be37e0b4d372aa60046f9ce771f12_r.jpg','https://pic-image.yesky.com/uploadImages/newPic/2023/188/04/7H87NC6W8T0A.png','https://c-ssl.duitang.com/uploads/item/202004/04/20200404163239_avipl.jpg','https://tse1-mm.cn.bing.net/th/id/OIP-C.njlhPi8v28sP8mpG3LlujwAAAA?rs=1&pid=ImgDetMain','https://tse2-mm.cn.bing.net/th/id/OIP-C.WgwRdIP_PFIE19eyu-cHgQHaJW?rs=1&pid=ImgDetMain']build() {Column() {WaterFlow() {ForEach(this.imgSrc, (item: string,index:number) => {FlowItem() {Image(item).width('100%').scale({ x:this.selectIndex===index? this.scaleXY:1, y: this.selectIndex===index? this.scaleXY:1 })}.onClick(() => {this.selectIndex = indexthis.getUIContext().keyframeAnimateTo({ iterations: 1 }, [{// 第一段关键帧动画时长为800ms,scale属性做从1到1.5的动画duration: 100,event: () => {this.scaleXY = 0.75;}},{// 第二段关键帧动画时长为500ms,scale属性做从1.5到1的动画duration: 200,event: () => {this.scaleXY = 1;}}])})})}.columnsTemplate('1fr 1fr').columnsGap(10).rowsGap(10)}.width('100%').padding(10)}
}

实战案例2:多组关键帧动画

import { UIContext } from '@kit.ArkUI';@Entry
@Component
struct MotionPathExample {uiContext: UIContext | undefined = undefined;aboutToAppear() {this.uiContext = this.getUIContext?.();}//  x、y、scale@State people: number[] = [0, 0, 1]@State star1: number[] = [40, -100, 1]@State star2: number[] = [60, -100, 1]@State star3: number[] = [80, -100, 1]build() {Column() {Stack({ alignContent: Alignment.Bottom }) {Image('https://pic.quanjing.com/0a/10/QJ8291629136.jpg@%21794ws').width(160).offset({ x: this.people[0], y: this.people[1] }).scale({ x: this.people[2], y: this.people[2] }).onClick(() => {if (this.uiContext) {this.uiContext.keyframeAnimateTo({ iterations: 1 }, [{// 第一段关键帧动画时长为800ms,scale属性做从1到1.5的动画duration: 2000,event: () => {this.people[0] = 40 // xthis.people[1] = -200 // ythis.people[2] = 1.2 // scalethis.star1[0] = 60 // xthis.star1[1] = -300 // ythis.star1[2] = 0.8 // scalethis.star2[0] = 90 // xthis.star2[1] = -300 // ythis.star3[2] = 0.8 // scalethis.star3[0] = 120 // xthis.star3[1] = -300 // ythis.star3[2] = 0.8 // scale}},{// 第二段关键帧动画时长为500ms,scale属性做从1.5到1的动画duration: 1500,event: () => {this.people[0] = 100 // xthis.people[1] = -300 // ythis.people[2] = 0.8 // scalethis.star1[0] = 100 // xthis.star1[1] = -400 // ythis.star2[0] = 100 // xthis.star2[1] = -400 // ythis.star3[0] = 100 // xthis.star3[1] = -400 // y}}]);}})Image('https://img0.baidu.com/it/u=2134749333,229655791&fm=253&fmt=auto&app=138&f=JPEG?w=300&h=277').width(30).offset({ x: this.star1[0], y: this.star1[1] }).scale({ x: this.star1[2], y: this.star1[2] })Image('https://img2.baidu.com/it/u=3837575474,649267201&fm=253&fmt=auto&app=138&f=PNG?w=304&h=304').width(20).offset({ x: this.star2[0], y: this.star2[1] }).scale({ x: this.star2[2], y: this.star2[2] })Image('https://img1.baidu.com/it/u=3978696291,2335621355&fm=253&fmt=auto&app=138&f=PNG?w=256&h=256').width(20).offset({ x: this.star3[0], y: this.star3[1] }).scale({ x: this.star3[2], y: this.star3[2] })}.width('100%').height('100%')}.width('100%').height('100%')}
}

实战案例3:抖动效果

可以查一下手机震动api效果更佳

@Entry
@Component
struct Index {@State translateX:number = 0build() {Column() {Text('请阅读并勾选协议').backgroundColor(Color.Black).fontColor(Color.White).padding({left:10,right:10,top:5,bottom:5}).margin({top:20,bottom:20}).translate({x:this.translateX})Button('本机号码号一键登录').onClick(() => {this.getUIContext().keyframeAnimateTo({ iterations: 2 }, [{// 第一段关键帧动画时长为50msduration: 50,event: () => {this.translateX = 5;}},{// 第二段关键帧动画时长为100msduration: 100,event: () => {this.translateX = 0;}}])})}}
}
  • 或者用显示动画也阔以
@Entry
@Component
struct Index {@State translateX:number = 0build() {Column() {Text('请阅读并勾选协议').backgroundColor(Color.Black).fontColor(Color.White).padding({left:10,right:10,top:5,bottom:5}).margin({top:20,bottom:20}).translate({x:this.translateX})Button('本机号码号一键登录').onClick(() => {animateTo({duration: 100,playMode: PlayMode.AlternateReverse,iterations: 3,// onFinish: () => {//   this.translateX = 0// }}, () => {this.translateX = 100})})}}
}

实战案例4:骨架片

@Entry
@Component
export struct Index {@State translateValue: string = '-100%'@State arr: number[] = [1,2,3,4,5]@State columnOpacityCom: number = 0.5;@State listItemHeight: string = '20%'@BuildercolumnShowBuilder(width: string, height: string, aspectRatioNum?: number) {Stack() {Column().linearGradient({angle: 90,colors: [['#f2f2f2', 0.25], ['#e6e6e6', 0.37], ['#f2f2f2', 0.63]],}).height('100%').width('100%')Column().height('100%').width('100%').translate({ x: this.translateValue }).linearGradient({angle: 90,colors: [['rgba(255,255,255,0)', 0],['rgba(255,255,255,1)', 0.5],['rgba(255,255,255,0)', 1]]})}.width(width).height(height).borderRadius(2).aspectRatio(aspectRatioNum).clip(true)}build() {Column() {List({ initialIndex: 0 }) {ForEach(this.arr, () => {ListItem() {Column({ space: 20 }) {Row({ space: 15 }) {this.columnShowBuilder('20%', '', 1)Column({ space: 10 }) {this.columnShowBuilder('50%', '25%')this.columnShowBuilder('30%', '20%')}.alignItems(HorizontalAlign.Start)}.justifyContent(FlexAlign.Start).width('100%').height('25%')Column({ space: 10 }) {this.columnShowBuilder('80%', '25%')this.columnShowBuilder('90%', '25%')this.columnShowBuilder('60%', '25%')}.alignItems(HorizontalAlign.Start).width('100%').height('25%')}.margin({ top: '4%', bottom: '2%' })}.width('90%').height(this.listItemHeight)}, (item: number) => JSON.stringify(item))}.width('100%').height('100%').alignListItem(ListItemAlign.Center).listDirection(Axis.Vertical).divider({ strokeWidth: 1, color: Color.Gray }).edgeEffect(EdgeEffect.Spring).scrollBar(BarState.Off).onAppear(() => {this.getUIContext().keyframeAnimateTo({iterations: -1,}, [{duration: 500,curve: Curve.Linear,event: () => {this.translateValue = '0'}},{duration: 500,curve: Curve.Linear,event: () => {this.translateValue = '100%'}},]);})}.width('100%').padding({ top: 10 })}
}

实战案例5:呼吸灯

  • 关键帧 也可以通过显示动画如下
@Entry
@Component
struct Index {@State myScale: number = 1uiContext: UIContext | undefined = undefined;@State timeId: number = 0@State @Watch("changeSpeed") speed: number = 0@State flag: boolean = falseaboutToAppear() {this.uiContext = this.getUIContext?.();this.timeId = setInterval(() => {this.speed++}, 500)}changeSpeed() {if (this.speed == 5) {// 触发关键帧动画if (!this.flag) this.haha()this.flag = !this.flag} else if (this.speed == 10) {clearInterval(this.timeId)this.timeId = setInterval(() => {this.speed--}, 500)} else if (this.speed == 0) {clearInterval(this.timeId)}}// 关键帧动画haha() {if (!this.uiContext) {console.info("no uiContext, keyframe failed");return;}this.myScale = 1;this.uiContext.keyframeAnimateTo({ iterations: 10 }, [{duration: 250,event: () => {this.myScale = 1.15;}},{duration: 250,event: () => {this.myScale = 1;}}])}build() {Column() {Column() {Column() {}.width(90).height(90).borderRadius(45).backgroundColor(Color.Blue).linearGradient({direction: GradientDirection.LeftBottom,colors: [[this.flag ? 'red' : 'blue', 0.1], [this.flag ? 'FFF18888' : '#ff00aeff', 0.9]]})}.width(100).height(100).borderRadius(50).backgroundColor(Color.White).justifyContent(FlexAlign.Center).scale({ x: this.myScale, y: this.myScale })Column() {Text(this.speed.toString()).fontWeight(FontWeight.Bold)Text('km/h')}.width(80).height(80).borderRadius(40).backgroundColor(Color.White).justifyContent(FlexAlign.Center).offset({ x: 0, y: -90 })}.width('100%').height('100%').backgroundColor(Color.Gray).justifyContent(FlexAlign.Center)}
}
  • 显示动画 还得调整下排版 自己来
@Entry
@Component
struct Index {@State scaleX: number = 1@State scaleY: number = 1build() {Text().width(50).height(50).backgroundColor(Color.Red).borderRadius(25).scale({ x: this.scaleX,  y: this.scaleY })   // 1 who ✅.onClick(()=>{  // 2 find&fixed 🔍 💕animateTo({duration: 2000,curve: Curve.EaseOut,iterations: -1},()=>{this.scaleX = 2this.scaleY = 2})})}
}

鸿蒙开发者班级

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/978351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS 开发应用沉浸式效果

开发应用沉浸式效果 概述 典型应用全屏窗口UI元素包括状态栏、应用界面和底部导航条,其中状态栏和导航条,通常在沉浸式布局下称为避让区;避让区之外的区域称为安全区。开发应用沉浸式效果主要指通过调整状态栏、应用…

HarmonyOS 属性动画.animation()

基础使用 - 1. 属性动画响应式(确定谁加动画) @State scaleX: number = 1 @State scaleY: number = 1Text().width(50).height(50).backgroundColor(Color.Red).scale({ x: this.scaleX, y: this.scaleY })- 2. 触发…

HarmonyOS游戏开发入门:用ArkTS打造经典五子棋

​ 引言 五子棋是一款经典的策略游戏,规则简单但乐趣无穷。本文将带你使用 HarmonyOS 的 ArkUI 框架,以组件化的思想快速实现一个双人对战的五子棋游戏。我们将逻辑与 UI 分离,打造一个结构清晰、易于维护的应用。 …

详细介绍:【论文阅读】AAAI 2025 | 面向精确分割式联邦学习的多模型聚合与知识重放

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Harmony ArkTS 并发编程全攻略:从基础概念到多线程实战,彻底搞懂性能优化

计算机基础概念在日常的生活或工作中,计算机几乎无处不在,特别是对于我们高级开发攻城狮来说、每天都要使用、来开发各种各样的程序,所以为了能够写出更好的程序、了解计算机基础知识是必要的,接下来就让我们来聊聊…

HarmonyOS文件操作进阶:上传/下载/解压全场景实战(含封装工具类)

​ 一、文件上传:从基础到企业级方案 文件上传是鸿蒙应用开发的核心场景(如头像上传、附件提交、图片分享),鸿蒙基于沙箱安全机制,要求上传文件必须先存入应用沙箱目录(cacheDir),再通过系统 API 提交。以下是…

HarmonyOS 文件操作不用愁:沙箱机制解析 + 可抄代码,零基础上手

一、应用沙箱:鸿蒙应用的 “安全文件柜”​核心简介​应用沙箱是鸿蒙系统为保障数据安全设计的隔离存储机制,每个应用都会获得专属的 “沙箱目录”,实现三大核心目标:​ 数据隔离:应用仅能访问自身文件和少量必需…

HarmonyOS ArkTS 状态管理 V2 全解析:新装饰器 + 实战示例 + 面试题(简述方便新手快速了解使用)

​ 鸿蒙 ArkTS 状态管理 V2 带来了一系列全新装饰器,不仅解决了 V1 版本中装饰器混淆、观测能力有限等问题,还强化了语义化和性能优化。本文将详细拆解@Local、@Param、@ObservedV2等核心装饰器,结合实战代码和对比…

2025最新机械密封件制造厂家实力榜!国内顶尖机械密封品牌权威发布,技术与服务双重保障,机械密封/机械密封件/釜用机械密封/双端面机械密封/机械密封维修品质与专业深度剖析,选择指南

随着工业设备对密封性能要求的不断提高,机械密封作为关键零部件,其质量与可靠性直接关系到生产安全与效率。本榜单基于技术研发实力、产品应用范围、服务响应速度三大维度,结合行业权威数据及用户反馈,对2025年国内…

八皇后

也是深搜实现,进去看看这条路可以走吗 #include <bits/stdc++.h> using namespace std; int ans=0; int m[50]; int mm[50]; int j[50]; int arr[50]; int n; void print() {if(ans>=3) return;for(int i=1;…

机器学习如何优化MRI扫描速度与质量

研究人员利用深度学习技术改进MRI扫描流程,通过随机采样和生成模型实现快速图像重建,减少患者扫描时间同时提升影像质量,该技术已在实际医疗场景中进行测试。机器学习如何优化MRI扫描速度与质量 对许多患者而言,磁…

【日记】买了几个手办(270 字)

正文今天比昨天睡得好,好耶 w。今天下单了几个盗版手办,这样一来我的机箱就不缺什么了。至于为什么是盗版…… 因为正版我买不起,哭哭。银河那边入金了一万,余额宝每天快速转账限额只有一万块钱,所以要达到入金要…

linux系统下独立声卡继电器总是自动反复吸合

在Linux系统下PCIe独立声卡出现反复吸合(不断断开又重连)的情况,确实挺让人头疼的。这个问题通常和电源管理、驱动兼容性或系统音频服务有关。别担心,我们可以一步步来排查。编辑ALSA基础配置文件:sudo nano /etc…

2025年有实力便携式烟灰缸定制/迷你便携式烟灰缸品牌厂家排行榜

2025年有实力便携式烟灰缸定制/迷你便携式烟灰缸品牌厂家排行榜 行业背景与市场趋势 随着全球控烟政策的推进与消费者环保意识的提升,便携式烟灰缸作为细分领域的刚需产品,市场潜力持续释放。据《2024年全球烟具行…

2025年3200度石墨化炉、卧式石墨化炉、碳纤维石墨化炉品

为帮助电池材料、碳纤维等行业企业精准筛选适配生产需求的高温石墨化炉设备,避免选型失误导致的产能损失与成本浪费,我们从设备核心性能(如极限温度稳定性、材料纯度控制精度)、行业场景适配性(针对负极材料/碳纤…

2025年度空调减震器制造企业排名:空调减震器制造企业选择哪

本榜单基于行业深度调研与真实用户反馈,围绕技术实力、产品质量、服务能力三大核心维度筛选出五家标杆企业,为有减震需求的客户提供客观参考,助力精准匹配专业供应商。 TOP1 推荐:河北亦辰减震器制造有限公司 推荐…

2025最新机械密封企业推荐!行业标杆企业权威榜单发布,技术与服务双优助力工业密封安全

随着工业制造领域对设备密封性能要求的不断提升,机械密封作为关键部件,其质量与可靠性直接关系到生产安全与效率。本榜单基于技术创新力、产品多样性、服务覆盖度三大维度,结合行业协会数据及市场反馈,权威解析202…

2025褪黑素哪个牌子好?7大品牌实测排行榜:入睡困难、失眠多梦人群必选

现代人群睡眠健康问题持续凸显:《2025 中国睡眠质量白皮书》数据显示,68.3% 的国人存在不同程度睡眠障碍,其中 49.2% 的成年人入睡时长超 52 分钟,39.6% 的人群每周夜间惊醒≥3 次,27.9% 因失眠导致深度睡眠占比不…

2025年11月建设工程律所评测榜:十家优质律所多维度对比分析

建设工程领域作为国民经济的支柱产业,其项目周期长、涉及主体多、法律关系复杂的特点,使得专业法律服务需求日益凸显。根据最新发布的行业白皮书显示,2025年我国建设工程市场规模持续扩大,但与此同时,工程合同纠纷…