鸿蒙特效教程09-深入学习animateTo动画

news/2025/3/29 10:39:36/文章来源:https://www.cnblogs.com/Megasu/p/18794477

鸿蒙特效教程09-深入学习animateTo动画

本教程将带领大家从零开始,一步步讲解如何讲解 animateTo 动画,并实现按钮交互效果,使新手也能轻松掌握。

效果演示

通过两个常见的按钮动画效果,深入学习 HarmonyOS Next 的 animateTo 动画,以及探索最佳实践。

  • 缩放按钮效果
  • 抖动按钮效果

image

一、基础准备

1.1 理解ArkUI中的动画机制

HarmonyOS的ArkUI框架提供了强大的动画支持,常见有两种实现方式:

  • 声明式动画:通过.animation()属性直接应用于组件
  • 命令式动画:通过animateTo()方法动态改变状态触发动画

本文将主要使用animateTo()方法,因为它更灵活,能实现更复杂的动画效果。

1.2 创建基础项目结构

首先,我们创建一个基本的页面组件结构:

@Entry
@Component
struct ButtonAnimation {// 状态变量将在后续步骤中添加build() {Column({ space: 20 }) {Text('按钮交互效果').fontSize(22).fontWeight(FontWeight.Bold)// 后续步骤将在这里添加按钮组件}.width('100%').height('100%').padding(20).backgroundColor('#ffb3d0ff').justifyContent(FlexAlign.Center).expandSafeArea()}
}

这段代码创建了一个基本的页面布局,包含一个标题文本。接下来,我们将逐步添加按钮和动画效果。

二、实现按钮点击缩放效果

2.1 添加基础按钮布局

首先,添加一个按钮及其容器:

// 按钮缩放效果
Column({ space: 10 }) {Text('按钮点击缩放效果').fontSize(16).fontWeight(FontWeight.Medium)Button('点击缩放').width(150).fontSize(16)// 动画相关属性将在后续步骤添加.onClick(() => {// 点击处理函数将在后续步骤添加console.log('按钮被点击了')})
}
.padding(16)
.borderRadius(12)
.backgroundColor('#F0F5FF')
.width('100%')
.margin({ top: 16 })
.alignItems(HorizontalAlign.Center)

这段代码添加了一个带标题的按钮区域,并为按钮设置了基本样式。

2.2 添加状态变量和缩放属性

要实现缩放效果,我们需要添加一个状态变量来控制按钮的缩放比例:

@State buttonScale: number = 1.0

然后,为按钮添加缩放属性:

Button('点击缩放').width(150).fontSize(16).scale({ x: this.buttonScale, y: this.buttonScale })  // 添加缩放属性.onClick(() => {console.log('按钮被点击了')})

.scale()属性用于设置组件的缩放比例,通过改变buttonScale的值,可以实现按钮的缩放效果。

2.3 实现简单的缩放动画

现在,添加一个简单的点击缩放效果:

// 按钮点击缩放效果
pressButton() {// 缩小animateTo({duration: 100,  // 动画持续时间(毫秒)curve: Curve.EaseIn  // 缓动曲线}, () => {this.buttonScale = 0.9  // 缩小到90%})// 延时后恢复原大小setTimeout(() => {animateTo({duration: 200,curve: Curve.EaseOut}, () => {this.buttonScale = 1.0  // 恢复原大小})}, 100)
}

然后修改按钮的点击处理函数:

.onClick(() => {this.pressButton()  // 调用缩放动画函数console.log('按钮被点击了')
})

这段代码实现了一个基本的缩放动画:按钮点击时先缩小到90%,然后恢复原大小。但是它使用了setTimeout,我们可以进一步优化。

2.4 使用onFinish回调优化动画

animateTo()方法提供了onFinish回调,可以在动画完成后执行操作。我们可以使用它来替代setTimeout

@State animationCount: number = 0  // 用于跟踪动画状态// 按钮点击缩放效果
pressButton() {this.animationCount = 0// 缩小animateTo({duration: 100,curve: Curve.EaseIn,  // 缓入曲线onFinish: () => {// 动画完成后立即开始第二阶段animateTo({duration: 200,curve: Curve.ExtremeDeceleration  // 急缓曲线}, () => {this.buttonScale = 1.0})}}, () => {this.animationCount++this.buttonScale = 0.9})
}

这种实现方式更加优雅,没有使用setTimeout,而是利用动画完成回调来链接多个动画阶段。此外,我们使用了不同的缓动曲线,使动画更加生动:

  • Curve.EaseIn:缓入曲线,动画开始时缓慢,然后加速
  • Curve.ExtremeDeceleration:急缓曲线,开始快速然后迅速减慢,产生弹性的视觉效果

三、实现按钮抖动效果

3.1 添加抖动按钮布局

先添加抖动按钮的UI部分:

// 抖动效果
Column({ space: 10 }) {Text('按钮抖动效果').fontSize(16).fontWeight(FontWeight.Medium)Button('点击抖动').width(150).fontSize(16)// 动画相关属性将在后续步骤添加.onClick(() => {console.log('按钮被点击了')})
}
.padding(16)
.borderRadius(12)
.backgroundColor('#F0F5FF')
.width('100%')
.alignItems(HorizontalAlign.Center)

3.2 添加状态变量和位移属性

要实现抖动效果,我们需要添加状态变量来控制按钮的水平位移:

@State shakeOffset: number = 0  // 控制水平抖动偏移
@State shakeStep: number = 0    // 用于跟踪抖动步骤

然后,为按钮添加平移属性:

Button('点击抖动').width(150).fontSize(16).translate({ x: this.shakeOffset })  // 添加水平平移属性.onClick(() => {console.log('按钮被点击了')})

.translate()属性用于设置组件的平移,通过改变shakeOffset的值,我们可以让按钮左右移动。

3.3 使用setTimeout实现连续抖动

一个简单的实现方式是使用多个setTimeout来创建连续的抖动:

// 抖动效果
startShake() {// 向右移动animateTo({ duration: 50 }, () => {this.shakeOffset = 5})// 向左移动setTimeout(() => {animateTo({ duration: 50 }, () => {this.shakeOffset = -5})}, 50)// 向右小幅移动setTimeout(() => {animateTo({ duration: 50 }, () => {this.shakeOffset = 3})}, 100)// 向左小幅移动setTimeout(() => {animateTo({ duration: 50 }, () => {this.shakeOffset = -3})}, 150)// 回到中心setTimeout(() => {animateTo({ duration: 50 }, () => {this.shakeOffset = 0})}, 200)
}

修改按钮的点击处理函数:

.onClick(() => {this.startShake()  // 调用抖动动画函数console.log('按钮被点击了')
})

这段代码通过多个setTimeout连续改变按钮的水平偏移量,实现抖动效果。但是使用这么多的setTimeout不够优雅,我们可以进一步优化。

3.4 使用递归和onFinish回调优化抖动动画

我们可以使用递归和onFinish回调来替代多个setTimeout,使代码更加优雅:

// 抖动效果
startShake() {this.shakeStep = 0this.executeShakeStep()
}// 执行抖动的每一步
executeShakeStep() {const shakeValues = [5, -5, 3, -3, 0]  // 定义抖动序列if (this.shakeStep >= shakeValues.length) {return  // 所有步骤完成后退出}animateTo({duration: 50,curve: Curve.Linear,  // 匀速曲线onFinish: () => {this.shakeStep++if (this.shakeStep < shakeValues.length) {this.executeShakeStep()  // 递归执行下一步抖动}}}, () => {this.shakeOffset = shakeValues[this.shakeStep]  // 设置当前步骤的偏移值})
}

这种实现方式更加优雅和灵活:

  1. 使用数组shakeValues定义整个抖动序列
  2. 通过递归调用executeShakeStep()onFinish回调,实现连续动画
  3. 没有使用setTimeout,使代码更加清晰和易于维护

四、animateTo API详解

animateTo()是HarmonyOS中实现动画的核心API,它的基本语法如下:

animateTo(value: AnimateParam, event: () => void): void

4.1 AnimateParam参数

AnimateParam是一个配置对象,包含以下主要属性:

  • duration: number - 动画持续时间,单位为毫秒
  • tempo: number - 动画播放速度,值越大动画播放越快,默认值 1
  • curve: Curve - 动画的缓动曲线,控制动画的速度变化
  • delay: number - 动画开始前的延迟时间,单位为毫秒
  • iterations: number - 动画重复次数,-1表示无限循环
  • playMode: PlayMode - 动画播放模式,如正向、反向、交替等
  • onFinish: () => void - 动画完成时的回调函数

4.2 常用缓动曲线

HarmonyOS提供了多种缓动曲线,可以实现不同的动画效果:

  • Curve.Linear: 线性曲线,动画速度恒定
  • Curve.EaseIn: 缓入曲线,动画开始缓慢,然后加速
  • Curve.EaseOut: 缓出曲线,动画开始快速,然后减速
  • Curve.EaseInOut: 缓入缓出曲线,动画开始和结束都缓慢,中间快速
  • Curve.FastOutSlowIn: 快出慢入曲线,类似于Android的标准曲线
  • Curve.ExtremeDeceleration: 急缓曲线,用于模拟弹性效果
  • curves.springMotion(): 弹簧曲线,模拟物理弹簧效果

4.3 动画函数

event是一个函数,在这个函数中改变状态变量的值,从而触发动画。例如:

animateTo({ duration: 300 }, () => {this.buttonScale = 0.9  // 改变状态变量,触发缩放动画
})

4.4 连续动画的实现方式

有几种方式可以实现连续的动画效果:

  1. 使用setTimeout(不推荐):

    animateTo({ duration: 300 }, () => { this.value1 = newValue1 })
    setTimeout(() => {animateTo({ duration: 300 }, () => { this.value2 = newValue2 })
    }, 300)
    
  2. 使用onFinish回调(推荐):

    animateTo({duration: 300,onFinish: () => {animateTo({ duration: 300 }, () => { this.value2 = newValue2 })}
    }, () => {this.value1 = newValue1
    })
    
  3. 使用递归和计数器(用于复杂序列):

    let steps = [value1, value2, value3]
    let currentStep = 0function executeNextStep() {if (currentStep >= steps.length) returnanimateTo({duration: 300,onFinish: () => {currentStep++if (currentStep < steps.length) {executeNextStep()}}}, () => {this.value = steps[currentStep]})
    }executeNextStep()
    

五、完整代码实现

下面是完整的按钮动画效果实现代码:

@Entry
@Component
struct ButtonAnimation {@State buttonScale: number = 1.0@State shakeOffset: number = 0@State animationCount: number = 0  // 用于跟踪动画状态@State shakeStep: number = 0  // 用于跟踪抖动步骤// 按钮点击缩放效果pressButton() {this.animationCount = 0// 缩小animateTo({duration: 100,curve: Curve.EaseIn,  // 缓入曲线onFinish: () => {// 动画完成后立即开始第二阶段animateTo({duration: 200,curve: Curve.ExtremeDeceleration  // 急缓曲线}, () => {this.buttonScale = 1.0})}}, () => {this.animationCount++this.buttonScale = 0.9})}// 抖动效果startShake() {this.shakeStep = 0this.executeShakeStep()}// 执行抖动的每一步executeShakeStep() {const shakeValues = [5, -5, 3, -3, 0]if (this.shakeStep >= shakeValues.length) {return}animateTo({duration: 50,curve: Curve.Linear,  // 匀速曲线onFinish: () => {this.shakeStep++if (this.shakeStep < shakeValues.length) {this.executeShakeStep()  // 递归执行下一步抖动}}}, () => {this.shakeOffset = shakeValues[this.shakeStep]})}build() {Column({ space: 20 }) {Text('按钮交互效果').fontSize(22).fontWeight(FontWeight.Bold)// 按钮缩放效果Column({ space: 10 }) {Text('按钮点击缩放效果').fontSize(16).fontWeight(FontWeight.Medium)Button('点击缩放').width(150).fontSize(16).scale({ x: this.buttonScale, y: this.buttonScale }).onClick(() => {// 缩放效果this.pressButton()// 你的业务逻辑console.log('你的业务逻辑')})}.padding(16).borderRadius(12).backgroundColor('#F0F5FF').width('100%').margin({ top: 16 }).alignItems(HorizontalAlign.Center)// 抖动效果Column({ space: 10 }) {Text('按钮抖动效果').fontSize(16).fontWeight(FontWeight.Medium)Button('点击抖动').width(150).fontSize(16).translate({ x: this.shakeOffset }).onClick(() => {// 你的业务逻辑console.log('你的业务逻辑')// 模拟轻微震动反馈,适用于错误提示或注意力引导this.startShake()})}.padding(16).borderRadius(12).backgroundColor('#F0F5FF').width('100%').alignItems(HorizontalAlign.Center)}.width('100%').height('100%').padding(20).backgroundColor('#ffb3d0ff').justifyContent(FlexAlign.Center).expandSafeArea()}
}

六、应用场景和扩展

6.1 适用场景

  • 缩放效果:适用于提供用户点击反馈,增强交互感
  • 抖动效果:适用于错误提示、警告或引起用户注意

6.2 可能的扩展

  1. 结合振动反馈:与设备振动结合,提供触觉反馈
  2. 添加声音反馈:配合音效,提供听觉反馈
  3. 组合多种动画:如缩放+旋转、缩放+颜色变化等

6.3 性能优化建议

  1. 避免过于复杂的动画,尤其是在低端设备上
  2. 合理选择动画持续时间,一般不超过300ms
  3. 对于频繁触发的动画,考虑增加防抖处理
  4. 使用onFinish回调代替setTimeout实现连续动画

七、总结与心得

通过本文,我们学习了如何在HarmonyOS中实现按钮缩放和抖动效果,关键点包括:

  1. 使用@State状态变量控制动画参数
  2. 利用animateTo()方法实现流畅的状态变化动画
  3. 选择合适的缓动曲线让动画更加自然
  4. 使用onFinish回调和递归实现连续动画,避免使用setTimeout
  5. 将动画逻辑封装为独立方法,使代码更加清晰

动画效果能够显著提升应用的用户体验,希望本文能帮助你在HarmonyOS应用中添加生动、自然的交互动画。随着你对 animateTo() API的深入理解,可以创造出更加复杂和精美的动画效果。

希望这篇 HarmonyOS Next 教程对你有所帮助,期待您的点赞、评论、收藏。

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

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

相关文章

鸿蒙特效教程10-卡片展开/收起效果

鸿蒙特效教程10-卡片展开/收起效果 在移动应用开发中,卡片是一种常见且实用的UI元素,能够将信息以紧凑且易于理解的方式呈现给用户。 本教程将详细讲解如何在HarmonyOS中实现卡片的展开/收起效果,通过这个实例,你将掌握ArkUI中状态管理和动画实现的核心技巧。 一、实现效果…

鸿蒙特效教程08-幸运大转盘抽奖

鸿蒙特效教程08-幸运大转盘抽奖本教程将带领大家从零开始,一步步实现一个完整的转盘抽奖效果,包括界面布局、Canvas绘制、动画效果和抽奖逻辑等。1. 需求分析与整体设计温馨提醒:本案例有一定难度,建议先收藏起来。在开始编码前,让我们先明确转盘抽奖的基本需求:展示一个…

ZGC圣经:ZGC垃圾回收器的原理、调优,ZGC 漏标的 分析与 研究

本文的 原始地址 ,传送门 本文的 原始地址 ,传送门 尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:听说你是高手,说说,你的ZGC 怎…

20242312 2024-2025-2 《Python程序设计》实验一报告

20242321 2024-2025-2 《Python程序设计》实验报告 课程:《Python程序设计》 班级: 2423 姓名: 周梓濠 学号:20242312 实验教师:王志强 实验日期:2025年3月12日 必修/选修: 公选课 1.实验内容 1.熟悉Python开发环境,配置VSCode; 2.配置gitee仓库,掌握git技能; 3.…

Tita:OKR 与项目管理、绩效一体化,助力企业实现目标驱动型发展

在当今竞争激烈的商业环境中,企业要想脱颖而出,实现可持续发展,明确目标、高效执行以及精准衡量结果至关重要。Tita 作为一款先进的管理平台,通过将 OKR(目标与关键成果法)与项目管理、绩效一体化相结合,为企业提供了一套完整的目标管理与执行解决方案,助力企业 “树目…

R语言绘图笔记—火山图

做个R语言绘图笔记,方便以后查看。 火山图:library(ggplot2) p1 <- ggplot(res, aes(x =log2FoldChange, y=-log10(pvalue), colour=sig)) + geom_point(size=2, shape = 16) + # 设置节点大小# 设置节点对应颜色scale_color_manual("significant" ,values=c(&…

git拉取代码到本地

1.先登入git,然后点击克隆,复制http地址:2.打开终端,输入 git clone http://xxxxxx3.然后在这个文件夹下就能看到复制的代码文件了4.可以把这个文件剪切到自己想要的路径下 5.pycharm打开就能用了

20232425 实验一 《python程序设计》实验报告

20232425 2024-2025-2 《Python程序设计》实验1报告 课程:《Python程序设计》 班级: 2324 姓名: 刘润民 学号:20232425 实验教师:王志强老师 实验日期:2025年3月12日 必修/选修: 公选课 一、实验内容 1、熟悉Python开发环境; 2、练习Python运行、调试技能;(编写书中的…

软件产品开发中常见的10个问题及处理方法

常见的10个问题 产品开发中常见的10个问题思维导图需求相关 1. 需求不明确 在日常工作中,需求来源于用户、老板、客户、竞品分析、业务部门、产品经理等,这些人或部门会提出需求,因为他们不是产品经理,提出的需求可能是一句话、一个想法这些简单的需求点,这些需求模糊且不…

025 登录页-记住密码的功能实现

这个页面这样写 这个页面这样写 这里定义两个常量 这里用常量代替 记住密码的勾选这样写

matplotlib之柱状图

# 柱状图 import matplotlib.pyplot as pltmovie_name = [雷神3:诸神黄昏,正义联盟,东方快车谋杀案,寻梦环游记,全球风暴,降魔传,追捕,横坐标] x = range(len(movie_name)) y = [73853,57767,22354,15969,14839,8725,8716,8318]plt.figure(figsize=(20,8), dpi=100) bars = plt…