HarmonyOS鸿蒙Next中用keyframeAnimateTo实现点赞的特效帧动画,如何避免出现不正常抖动

HarmonyOS鸿蒙Next中用keyframeAnimateTo实现点赞的特效帧动画,如何避免出现不正常抖动

【问题现象】

keyframeAnimateTo实现一个点赞的特效帧动画,图片在往上飘的时候,会出现左右抖动的现象。

【背景知识】

【定位思路】

点赞的特效可以通过keyframeAnimateTo实现。

  • 通过设置帧数,插值曲线,以及在event里面设置自定义的效果来实现动画效果。
  • 点赞效果,通过在event里面动态改变图片的透明度,矩阵,以及轴和y轴的位置来实现让点赞的图片像炊烟一样上飘的特效。

点击放大

示例代码如下:

// 用list来设定点赞图片的运动轨迹 
{
  //  该段关键帧动画的持续时间,单位为毫秒。 取值范围:[0, +∞)
  duration: 1,
  // 指定在该关键帧时刻状态的闭包函数,即在该关键帧时刻要达到的状态。
  event:
  () => {
    this.scaleArray[index] = 0;
    this.opacityArray[index] = 0;
    this.offYArray[index] = 0;
    this.offXArray[index] = 0;
  }
},
{
  duration: getRandomInt(MIN_ANM_DURATION, MAX_ANM_DURATION),
  event:
  () => {
    this.scaleArray[index] = 0.3;
    this.opacityArray[index] = 0.5;
    this.offYArray[index] = -15;
    let xArray = getRandomInt(MIN_OFFSET_X, MAX_OFFSET_X);
    this.offXArray[index] = xArray;
  }
},
{
  duration: getRandomInt(MIN_ANM_DURATION, MAX_ANM_DURATION),
  event:
  () => {
    this.scaleArray[index] = 0.5;
    this.opacityArray[index] = 0.8;
    this.offYArray[index] = -30;
    let xArray = getRandomInt(MIN_OFFSET_X, MAX_OFFSET_X);
    this.offXArray[index] = xArray;
  }
}

动画效果的Curve效果默认为EaseInOut,查询文档发现,curve的动画效果一共有以下几种:

名称 描述
Linear 表示动画从头到尾的速度都是相同的。
Ease 表示动画以低速开始,然后加快,在结束前变慢,CubicBezier(0.25, 0.1, 0.25, 1.0)。
EaseIn 表示动画以低速开始,CubicBezier(0.42, 0.0, 1.0, 1.0)。
EaseOut 表示动画以低速结束,CubicBezier(0.0, 0.0, 0.58, 1.0)。
EaseInOut 表示动画以低速开始和结束,CubicBezier(0.42, 0.0, 0.58, 1.0)。
FastOutSlowIn 标准曲线,CubicBezier(0.4, 0.0, 0.2, 1.0)。
LinearOutSlowIn 减速曲线,CubicBezier(0.0, 0.0, 0.2, 1.0)。
FastOutLinearIn 加速曲线,CubicBezier(0.4, 0.0, 1.0, 1.0)。
ExtremeDeceleration 急缓曲线,CubicBezier(0.0, 0.0, 0.0, 1.0)。
Sharp 锐利曲线,CubicBezier(0.33, 0.0, 0.67, 1.0)。
Rhythm 节奏曲线,CubicBezier(0.7, 0.0, 0.2, 1.0)。
Smooth 平滑曲线,CubicBezier(0.4, 0.0, 0.4, 1.0)。
Friction 阻尼曲线,CubicBezier(0.2, 0.0, 0.2, 1.0)。

其中Linear匀速运动,所以不会出现抖动,而其余动画效果则会出现各种曲线和速度变化,从而出现抖动的效果。

【解决方案】

修改Curve值,把Curve值改成Linear,就可以消除抖动效果。

示例代码如下:

// 表示动画从头到尾的速度都是相同的
const cur = Curve.Linear;
{
  duration: getRandomInt(MIN_ANM_DURATION, MAX_ANM_DURATION),
  curve:
  cur,
  event:
  () => {
    this.scaleArray[index] = 0.3;
    this.opacityArray[index] = 0.5;
    this.offYArray[index] = -15;
    let xArray = getRandomInt(MIN_OFFSET_X, MAX_OFFSET_X);
    this.offXArray[index] = xArray;
  }
}

核心代码如下:

const cur = Curve.Linear;
/**
 * 点赞动画
 * 0, 1.18, 0.86, 1
 */
clickAnimation() {
  if (!this.uiContext) {
    return;
  }
  let index = getRandomInt(0, NUMBER_OF_ITEMS);
  index = index >= NUMBER_OF_ITEMS ? 0 : index;
  while (this.flag[index] === true) {
    index = getRandomInt(0, NUMBER_OF_ITEMS);
    index = index >= NUMBER_OF_ITEMS ? 0 : index;
  }
  this.flag[index] = true;
  this.uiContext.keyframeAnimateTo({
    iterations: 1, onFinish: () => {
      this.flag[index] = false;
    }
  }, [
    {
      duration: 1,
      curve: cur,
      event: () => {
        this.scaleArray[index] = 0;
        this.opacityArray[index] = 0;
        this.offYArray[index] = 0;
        this.offXArray[index] = 0;
      }
    },
    {
      duration: getRandomInt(MIN_ANM_DURATION, MAX_ANM_DURATION),
      // 动画效果
      curve: cur,
      event: () => {
        this.scaleArray[index] = 0.3;
        this.opacityArray[index] = 0.5;
        this.offYArray[index] = -15;
        let xArray = getRandomInt(MIN_OFFSET_X, MAX_OFFSET_X);
        this.offXArray[index] = xArray;
      }
    }
  ])
}

function getRandomInt(min: number, max: number): number {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

更多关于HarmonyOS鸿蒙Next中用keyframeAnimateTo实现点赞的特效帧动画,如何避免出现不正常抖动的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中用keyframeAnimateTo实现点赞的特效帧动画,如何避免出现不正常抖动的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


Curve值改为Linear,可以避免动画抖动。示例代码如下:

const cur = Curve.Linear;
{
  duration: getRandomInt(MIN_ANM_DURATION, MAX_ANM_DURATION),
  curve: cur,
  event: () => {
    this.scaleArray[index] = 0.3;
    this.opacityArray[index] = 0.5;
    this.offYArray[index] = -15;
    let xArray = getRandomInt(MIN_OFFSET_X, MAX_OFFSET_X);
    this.offXArray[index] = xArray;
  }
}
回到顶部