HarmonyOS 鸿蒙Next如何实现安卓中的OvershootInterpolator

HarmonyOS 鸿蒙Next如何实现安卓中的OvershootInterpolator OvershootInterpolator(1f) 是 Android 动画中的一个插值器(Interpolator),它控制动画的“节奏”,让动画在接近目标时冲过头(overshoot),然后再弹回来,产生一种有弹性的、生动的效果。

请问鸿蒙中如何实现同样的效果?我在animateTo中没找到对应的Param

6 回复

鸿蒙的 Curves 模块提供了 interpolatingSpring 弹簧曲线,能够模拟超过目标值后回弹的效果,与 OvershootInterpolator 功能一致。

通过 Curves.interpolatingSpring 创建插值器,可调节 velocity(初始速度)、mass(质量)、stiffness(刚度)、damping(阻尼)等参数:

import { Curves } from '@kit.ArkUI';

// 参数示例(需根据实际效果调整)
const overshootCurve = Curves.interpolatingSpring({
  velocity: 0,   // 初始速度
  mass: 1,       // 质量(影响惯性)
  stiffness: 300,// 刚度(越大回弹越快)
  damping: 10    // 阻尼(越小超调越明显)
});

在 animateTo 或 animation 中使用该曲线驱动属性变化:

// 使用 animateTo
animateTo({
  duration: 1000,
  curve: overshootCurve
}, () => {
  this.translateY = 200;  // 目标属性值
});

// 使用 animation 修饰符
Text()
  .translate({ y: this.translateY })
  .animation({
    curve: overshootCurve,
    duration: 1000
  })

更多关于HarmonyOS 鸿蒙Next如何实现安卓中的OvershootInterpolator的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


使用curves设置弹簧曲线

@Entry
@Component
struct Index {
  @State xcWidth: number = 0;

  build() {
    Column({ space: 5 }) {
      Row()
        .width(this.xcWidth)
        .height(100)
        .backgroundColor(Color.Red)
        .animation({
          duration: 3000, //动画持续时间,单位为毫秒。默认值:1000
          // 在ArkTS卡片上最大动画持续时间为1000毫秒,若超出则固定为1000毫秒。
          // - 设置小于0的值时按0处理。Ò
          // - 设置浮点型类型的值时,向下取整。例如,设置值为1.2,按照1处理。
          tempo: 1, //动画播放速度,值越大动画播放越快,值越小播放越慢,为0时无动画 默认值:1.0  当设置小于0的值时按值为1处理
          curve: Curve.Linear, //表示动画从头到尾的速度都是相同的。
          // curve: Curve.Ease	,//表示动画以低速开始,然后加快,在结束前变慢,cubic-bezier(0.25, 0.1, 0.25, 1.0)。
          // curve: Curve.EaseIn	,//表示动画以低速开始,cubic-bezier(0.42, 0.0, 1.0, 1.0)。
          // curve: Curve.EaseOut	,//表示动画以低速结束,cubic-bezier(0.0, 0.0, 0.58, 1.0)。
          // curve: Curve.EaseInOut	,//表示动画以低速开始和结束,cubic-bezier(0.42, 0.0, 0.58, 1.0)。
          // curve: Curve.FastOutSlowIn	,//标准曲线,cubic-bezier(0.4, 0.0, 0.2, 1.0)。
          // curve: Curve.LinearOutSlowIn	,//减速曲线,cubic-bezier(0.0, 0.0, 0.2, 1.0)。
          // curve: Curve.FastOutLinearIn	,//加速曲线,cubic-bezier(0.4, 0.0, 1.0, 1.0)。
          // curve: Curve.ExtremeDeceleration	,//急缓曲线,cubic-bezier(0.0, 0.0, 0.0, 1.0)。
          // curve: Curve.Sharp	,//锐利曲线,cubic-bezier(0.33, 0.0, 0.67, 1.0)。
          // curve: Curve.Rhythm	,//节奏曲线,cubic-bezier(0.7, 0.0, 0.2, 1.0)。
          // curve: Curve.Smooth	,//平滑曲线,cubic-bezier(0.4, 0.0, 0.4, 1.0)。
          // curve: Curve.Friction	,//阻尼曲线,cubic-bezier(0.2, 0.0, 0.2, 1.0)。
          delay: -1500, //动画延迟播放时间,单位为ms(毫秒),默认不延时播放。默认值:0 (-∞, +∞)
          //delay>=0为延迟播放,delay<0表示提前播放。
          //对于delay<0的情况:当delay的绝对值小于实际动画时长,动画将在开始后第一帧直接运动到delay绝对值的时刻的状态;
          // 当delay的绝对值大于等于实际动画时长,动画将在开始后第一帧直接运动到终点状态。其中实际动画时长等于单次动画时长乘以动画播放次数。
          // 设置浮点型类型的值时,向下取整。例如,设置值为1.2,按照1处理。
          iterations: 10, //动画播放次数。默认播放一次, 设置-1表示动画无限循环 设置为0时表示无动画效果 默认值:1 取值范围:[-1, +∞) 小于-1只执行一次 输入小数向下取整
          playMode: PlayMode.Normal, //动画播放模式,默认播放完成后重头开始播放  动画正向播放。
          // playMode: PlayMode.Reverse,//动画反向播放。
          // playMode: PlayMode.Alternate,//动画在奇数次(1、3、5...)正向播放,在偶数次(2、4、6...)反向播放。
          // playMode: PlayMode.AlternateReverse,//动画在奇数次(1、3、5...)反向播放,在偶数次(2、4、6...)正向播放。
          onFinish: () => { //动画播放完成回调。UIAbility从前台切换至后台时会立即结束仍在步进中的有限循环动画,触发播放完成回调。
            console.log("animation:", "动画播放结束!")
          },
          //在动画中定义onFinish回调的类型。
          finishCallbackType: FinishCallbackType.REMOVED, //当整个动画结束并立即删除时,将触发回调。
          // finishCallbackType: FinishCallbackType.LOGICALLY, //当动画在逻辑上处于下降状态,但可能仍处于其长尾状态时,将触发回调。
          //设置动画的期望帧率。
          expectedFrameRateRange: {
            min: 20,//期望的最小帧率。
            max: 120,//期望的最大帧率。
            expected: 90,//期望的最优帧率。
          }
        })
      Button("change size")
        .onClick(() => {
          this.xcWidth = 200;
        })
    }
    .width("100%")
  }
}
  1. 使用 Curves.interpolatingSpring
    鸿蒙提供了弹簧插值器 Curves.interpolatingSpring,能够生成带有过冲(overshoot)效果的动画曲线。通过调整**张力(tension)摩擦力(friction)**参数,可以控制过冲幅度:

    • 张力(tension):值越大,弹簧越“紧”,过冲幅度越小。
    • 摩擦力(friction):值越大,回弹次数越少,过冲后更快稳定。
  2. animateTo结合使用
    animateTo是鸿蒙显式动画接口,通过闭包内的属性变化触发动画。将弹簧插值器作为参数传递给 animateTo即可实现弹性动画。

你说的应该是List之类的滑动组件中的动画问题,目前可以通过设置

.edgeEffect(EdgeEffect.None)

来设置相关效果。如:Spring、Fade等

HarmonyOS Next中实现类似安卓OvershootInterpolator效果,可使用系统提供的插值器曲线。在动画开发中,通过Curve.Spring或自定义Curve实现弹性效果。具体使用animateTo时指定curve: Curve.Spring参数,或使用Curve.interpolatingSpring创建自定义弹性曲线,调整阻尼、刚度等参数模拟Overshoot效果。

在HarmonyOS Next中,可以通过自定义曲线插值器(Curve) 来实现Android OvershootInterpolator的效果。

HarmonyOS的动画系统使用Curve对象(而非Android的Interpolator)来定义动画变化速率。系统未直接提供OvershootInterpolator,但可以通过组合或自定义曲线来模拟。

核心方案:使用SpringCurve或自定义Curve

1. 推荐方案:使用SpringCurve(弹簧曲线)

SpringCurve能直接创建出“冲过头再弹回”的弹性效果,与OvershootInterpolator的物理行为高度一致。

import { Curve, SpringCurve } from '@kit.ArkUI';

// 创建弹簧曲线,参数可调整以匹配Android的1.0张力值
// 参数说明:velocity(初始速度), mass(质量), stiffness(刚度), damping(阻尼)
const overshootCurve: Curve = new SpringCurve(0.0, 1.0, 300.0, 20.0);

// 在animateTo中使用
animateTo({
  duration: 500, // 动画时长
  curve: overshootCurve, // 应用自定义曲线
  onFinish: () => {
    // 动画完成回调
  }
}, () => {
  // 在此处改变状态变量,驱动UI动画
  this.targetX = 200;
  this.targetOpacity = 1.0;
});

参数调优建议

  • 调整stiffness(刚度)和damping(阻尼)可控制“冲过头”的幅度和回弹次数。
  • 要精确匹配Android OvershootInterpolator(1f),需微调参数。较高的stiffness(如300-500)和较低的damping(如10-30)会产生明显的过冲。

2. 备用方案:自定义Curve

若需精确控制过冲的数学行为(如Android标准实现),可继承Curve类并实现插值方法。

import { Curve } from '@kit.ArkUI';

class OvershootCurve extends Curve {
  private tension: number;

  constructor(tension: number = 1.0) {
    super();
    this.tension = tension;
  }

  // 实现插值计算
  interpolate(fraction: number): number {
    // 基于Android OvershootInterpolator公式实现
    // fraction为输入进度[0,1],返回值为转换后的进度(可超过1.0)
    if (fraction === 0.0 || fraction === 1.0) {
      return fraction;
    }
    // 简化公式示例:实际需实现完整计算
    return fraction - 1.0 - this.tension * Math.sin(fraction * Math.PI * 2.0) * 0.5;
  }
}

// 使用方式
const myCurve = new OvershootCurve(1.0);
animateTo({
  curve: myCurve,
  // ... 其他参数
});

关键区别说明

  • 概念映射:HarmonyOS的Curve ≈ Android的Interpolator
  • 参数位置:在animateTo的配置对象中,通过curve字段指定,而非直接作为参数。
  • 系统曲线:HarmonyOS内置了Curve.EaseCurve.Linear等,但未直接提供Overshoot。

调试建议

  1. 使用SpringCurve并实时调整参数,通过预览观察效果。
  2. 动画时长(duration)会影响弹性效果的展现,建议设置在300-600ms。
  3. 可同时动画化多个属性(如位置、透明度、缩放),它们将共享同一曲线。

通过上述方案,可在HarmonyOS Next中实现与Android OvershootInterpolator等效的动画效果。

回到顶部