HarmonyOS7 脉冲动画:循环缩放效果的实现与踩坑

HarmonyOS7 脉冲动画:循环缩放效果的实现与踩坑
文章目录前言反面教材正确姿势状态定义脉冲动画元素核心循环逻辑停止脉冲原理解析为什么放大用 EaseOut缩小用 EaseIn透明度配合的妙处实践清单写在最后前言有一种动画效果你肯定见过——微信语音消息旁边那个绿色圆圈一直在放大缩小像在呼吸一样。这叫脉冲动画Pulse Animation常见于消息提醒、定位按钮、录音状态指示等场景。脉冲动画看起来简单不就是放大再缩小吗但真正做起来有几个细节容易踩坑。今天就来聊聊在 ArkUI 里怎么实现一个靠谱的脉冲动画。反面教材先看一个典型的错误写法// 错误直接用 .animation 的 iterations 参数Column().scale({x:this.pulseScale,y:this.pulseScale}).animation({duration:600,iterations:-1,// 无限循环curve:Curve.EaseInOut})这个写法理论上没问题.animation的iterations: -1确实可以让动画无限循环。但有个致命问题——你没法在循环过程中动态控制动画的暂停和恢复。一旦跑起来就停不下来了。所以我们需要用setTimeout手动管理循环。正确姿势状态定义EntryComponentstruct PulseAnimation{StatepulseScale:number1StatepulseOpacity:number1StateisPulsing:booleanfalseprivatepulseTimer:number-1build(){Column(){// ...}}}isPulsing是一个控制标记用来决定循环是否继续。脉冲动画元素Stack(){Column().width(60).height(60).backgroundColor(#4D96FF).borderRadius(30).scale({x:this.pulseScale,y:this.pulseScale}).opacity(this.pulseOpacity).animation({duration:600,curve:Curve.EaseInOut})Text(P).fontSize(22).fontColor(#FFFFFF).fontWeight(FontWeight.Bold)}.width(80).height(80)用Stack把脉冲圆圈和文字叠在一起。圆圈做动画文字保持不动——这样视觉效果是圆圈在脉冲文字不动。核心循环逻辑Button(开始脉冲).onClick((){if(this.isPulsing)returnthis.isPulsingtrueconstpulse(){if(!this.isPulsing){this.pulseScale1this.pulseOpacity1return}// 阶段1放大 变透明animateTo({duration:600,curve:Curve.EaseOut},(){this.pulseScale1.3this.pulseOpacity0.5})// 阶段2缩小 恢复不透明setTimeout((){animateTo({duration:600,curve:Curve.EaseIn},(){this.pulseScale1this.pulseOpacity1})// 延迟200ms后开始下一轮if(this.isPulsing)setTimeout(pulse,200)},600)}pulse()})这个递归函数的执行流程检查isPulsing标记如果为false就停下来并恢复初始状态用animateTo执行放大 变透明600ms等 600ms 后用animateTo执行缩小 恢复600ms再等 200ms 的间隔然后递归调用自身每一轮脉冲的总时长是600 600 200 1400ms。停止脉冲Button(停止脉冲).onClick((){this.isPulsingfalse})停止时只需要把isPulsing设为false。当前一轮动画跑完后递归函数检查到标记变化就会自动退出。原理解析为什么放大用 EaseOut缩小用 EaseIn这不是随便选的放大阶段用Curve.EaseOut快速开始放大然后慢慢减速到最大。视觉上像是弹出去缩小阶段用Curve.EaseIn慢慢开始缩小然后加速回到原位。视觉上像是弹回来这两段曲线拼在一起就形成了一个自然的弹性脉冲效果。透明度配合的妙处只做缩放的话脉冲效果看起来像个弹簧。加上透明度变化后放大时变透明缩小时恢复不透明视觉上更像一个发光脉冲或者雷达扫描。实践清单实现脉冲动画时的检查清单用isPulsing标记控制循环不要用iterations: -1放大和缩小用不同的动画曲线配合透明度变化增加质感停止脉冲时恢复初始状态防止重复启动if (this.isPulsing) return写在最后脉冲动画的核心就是用递归setTimeout来手动管理循环而不是依赖.animation的iterations参数。虽然代码多几行但换来了完全的控制权——想停就停想变就变。这种手动循环的思路不只适用于脉冲动画后面聊到的呼吸灯、加载动画也会用到同样的模式。