HarmonyOS7 五种 Curve 曲线对比:Linear、EaseIn、EaseOut、EaseInOut、Spring 动画实测

HarmonyOS7 五种 Curve 曲线对比:Linear、EaseIn、EaseOut、EaseInOut、Spring 动画实测 文章目录前言为什么需要对比方案对比表选型建议详细实现状态管理进度条列表启动对比动画启动函数重置优劣分析实际案例场景一弹窗入场场景二列表项删除场景三主题切换完整的 Curve 速查表写在最后前言动画的灵魂不在时长、不在属性而在Curve 曲线。同样的位移、同样的时长换一个 Curve 就完全是不同的感觉。但 Curve 的种类这么多到底哪个适合哪个场景今天做一个可视化的对比实验——5 条进度条用 5 种不同 Curve同时启动肉眼对比它们的运动差异。为什么需要对比很多人选 Curve 全靠感觉——哪个看着顺眼用哪个。但如果理解了每种曲线的数学特性选型会更有依据为什么按钮点击用EaseOut为什么加载转圈用Linear为什么弹窗用EaseInOut答案都在曲线的速度-时间关系里。方案对比表先上数据五种曲线的运动特征对比Curve起始速度终止速度中间速度视觉感受| Linear | 恒定 | 恒定 | 恒定 | 匀速机械 || EaseIn | 慢 | 快 | 渐快 | 缓慢启动加速冲出 || EaseOut | 快 | 慢 | 渐慢 | 快速启动慢慢停稳 || EaseInOut | 慢 | 慢 | 快 | 平滑过渡最自然 || FastOutLinearIn | 快 | 中 | 渐慢 | 快速冲出线性减速 |选型建议场景推荐 Curve原因元素入场EaseOut快速出现慢慢停稳元素出场EaseIn慢慢开始快速消失状态切换EaseInOut平滑过渡不突兀加载旋转Linear匀速转动不忽快忽慢进度条EaseInOut开始和结束都柔和弹出菜单FastOutLinearIn快速弹出线性停稳弹性效果Rhythm / springMotion有过冲回弹详细实现状态管理EntryComponentstruct CurveComparisonPanel{Statepositions:number[][0,0,0,0,0]Statelabels:string[][Linear,EaseIn,EaseOut,EaseInOut,Spring]// ...}positions是一个长度为 5 的数组每个元素代表一条进度条的当前进度百分比。labels是每条进度条对应的 Curve 名称。进度条列表ForEach([0,1,2,3,4],(idx:number){Row(){Text(this.labels[idx]).width(70).fontSize(11).fontColor(#999999)Stack({alignContent:Alignment.Start}){// 底层灰色条Column().width(100%).height(8).backgroundColor(#E0E0E0).borderRadius(4)// 上层彩色条Column().width(${this.positions[idx]}%).height(8).backgroundColor(PRESET_COLORS[idx].value).borderRadius(4).animation({duration:1500})}.layoutWeight(1)}.width(100%).height(36).alignItems(VerticalAlign.Center)})每条进度条的结构左侧 70vp 宽的文字标签Curve 名称右侧 Stack 叠放两层灰色底 彩色进度每条进度条用不同的颜色PRESET_COLORS[idx]方便区分注意.animation({ duration: 1500 })设了 1500ms 的时长。之所以用 1.5 秒而不是更短是因为时长太短的话不同 Curve 的差异看不出来——都是一闪就完了。启动对比Button(启动对比).onClick((){this._startAnimation(0,Curve.Linear)this._startAnimation(1,Curve.EaseIn)this._startAnimation(2,Curve.EaseOut)this._startAnimation(3,Curve.EaseInOut)this._startAnimation(4,Curve.FastOutLinearIn)})5 条进度条同时启动各自使用不同的 Curve。动画启动函数_startAnimation(index:number,curve:Curve|string){animateTo({duration:1500,curve:curve},(){this.positions[index]90})}统一的启动函数传入索引和 Curve 类型。每个animateTo调用独立控制一条进度条互不干扰。重置Button(重置).onClick((){for(leti0;i5;i){this.positions[i]0}})直接赋值归零不走动画因为没包animateTo。优劣分析观察 5 条进度条的运动过程可以得出这些结论Linear线性从 0% 到 90% 速度完全一致适合需要恒定速度的场景加载转圈、秒表在 UI 过渡中显得机械不推荐用于交互反馈EaseIn缓入前半段很慢后半段加速观察时会觉得怎么还不走然后嗖的一下到了适合元素出场慢慢开始动然后快速消失EaseOut缓出前半段很快后半段减速“嗖的一下冲出去然后慢慢停稳”最适合入场动画快速出现慢慢停稳用户感知最强EaseInOut缓入缓出两头慢中间快最平衡视觉上最自然没有突然的加速或减速万能曲线不知道用啥就用它FastOutLinearIn快出线性入起步非常快然后匀速减速介于 EaseOut 和 Linear 之间适合弹出式交互弹窗、菜单快速出现实际案例场景一弹窗入场animateTo({duration:300,curve:Curve.EaseOut},(){this.dialogOpacity1this.dialogScale1})弹窗从透明缩小→不透明正常大小。EaseOut让弹窗快速弹出慢慢停稳。场景二列表项删除animateTo({duration:200,curve:Curve.EaseIn},(){this.itemOpacity0this.itemTranslateX-100})列表项慢慢开始移动然后快速滑出屏幕。EaseIn给用户一个准备的时间。场景三主题切换animateTo({duration:800,curve:Curve.EaseInOut},(){this.backgroundColorisDark?#1A1A1A:#FFFFFFthis.textColorisDark?#FFFFFF:#333333})整体颜色渐变EaseInOut让过渡最自然。完整的 Curve 速查表Curve一句话描述最佳场景Linear匀速加载旋转EaseIn慢进快出元素出场EaseOut快进慢出元素入场EaseInOut慢快慢状态切换FastOutSlowIn极快启动慢停弹性位移FastOutLinearIn快启动匀减速弹出菜单ExtremeDeceleration极快急停强调效果Rhythm节奏性过冲弹性缩放Sharp尖锐快速反馈这个对比实验建议自己在真机上跑一遍。文章里的描述再详细不如亲眼看到 5 条进度条同时跑起来的差异直观。1.5 秒的时长足够你看清每种曲线的个性。写在最后Curve 曲线是动画的性格。同样的起止点、同样的时长换个 Curve 就是完全不同的感受。做 UI 动画时别只用一个EaseInOut打天下——入场用EaseOut出场用EaseIn切换用EaseInOut弹性用Rhythm。根据场景选对曲线动画的质感就上去了。