温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦!

HarmonyOS NEXT系列教程之 TabsConcaveCircle组件动画系统详解

本文将深入解析TabsConcaveCircle组件的动画系统实现,包括选项切换动画和圆球移动动画。

效果演示

1. 动画状态管理

private canvasAnimator: AnimatorResult | undefined = undefined;
@State animateTime: number = 1000;
@State animationPositionX: number = 0;
@State imageOffsetY: number = 0;
@State imageWH: number = 0;

动画相关状态说明:

  1. 动画控制器:

    • canvasAnimator: 存储动画实例
    • 用于控制动画的播放和暂停
  2. 动画参数:

    • animateTime: 动画持续时间
    • animationPositionX: 当前凹槽位置
    • imageOffsetY: 图片偏移量
    • imageWH: 图片尺寸

2. 选项切换动画

getAnimateSelectIndex() {
  let animateDelay = 500;
  animateTo({
    duration: this.animateTime,
    delay: animateDelay
  }, () => {
    this.animateSelectIndex = this.selectIndex
  })
  this.createAnimation()
}

切换动画实现:

  1. 动画配置:

    • animateDelay: 500ms延迟
    • duration: 动画持续时间
  2. 状态更新:

    this.animateSelectIndex = this.selectIndex
    • 同步选中状态
    • 触发UI更新
  3. 动画联动:

    this.createAnimation()
    • 触发圆球移动动画
    • 实现联动效果

3. 圆球移动动画

createAnimation() {
  if (!this.circleInfo) {
    return;
  }
  
  this.canvasAnimator = animator.create({
    duration: this.animateTime,
    easing: "ease",
    delay: 0,
    fill: "forwards",
    direction: "normal",
    iterations: 1,
    begin: this.animationPositionX,
    end: this.circleInfo?.getMenuCenterX(this.selectIndex)
  })
  
  this.canvasAnimator.onFrame = (value: number) => {
    this.animationPositionX = value;
    this.circleInfo?.setPositionXY({ x: value - this.circleInfo.circleRadius })
    this.createCanvas()
  }
  
  this.canvasAnimator.play()
}

移动动画详解:

  1. 动画创建:

    animator.create({
      duration: this.animateTime,
      easing: "ease",
      fill: "forwards",
      direction: "normal",
      iterations: 1,
      begin: this.animationPositionX,
      end: this.circleInfo?.getMenuCenterX(this.selectIndex)
    })
    • 设置动画时长
    • 使用ease缓动函数
    • 保持最终状态
    • 设置起始和结束位置
  2. 帧动画处理:

    this.canvasAnimator.onFrame = (value: number) => {
      this.animationPositionX = value;
      this.circleInfo?.setPositionXY({ x: value - this.circleInfo.circleRadius })
      this.createCanvas()
    }
    • 更新位置状态
    • 设置圆球位置
    • 重绘Canvas内容
  3. 动画控制:

    this.canvasAnimator.play()
    • 启动动画
    • 自动执行帧更新

4. Canvas重绘实现

createCanvas() {
  if (this.circleInfo) {
    this.context.reset()
    CanvasCreateRectangle({
      context: this.context,
      tabsBgColor: this.tabsBgColor
    })
    CanvasClipGroove({
      context: this.context,
      menuLength: this.tabsMenu.length,
      center: this.animationPositionX,
    })
  }
}

Canvas更新流程:

  1. 重置画布:

    this.context.reset()
    • 清除旧内容
    • 准备新一帧
  2. 绘制背景:

    CanvasCreateRectangle({
      context: this.context,
      tabsBgColor: this.tabsBgColor
    })
    • 创建矩形背景
    • 应用背景颜色
  3. 创建凹槽:

    CanvasClipGroove({
      context: this.context,
      menuLength: this.tabsMenu.length,
      center: this.animationPositionX,
    })
    • 绘制凹槽效果
    • 使用当前位置

总结

TabsConcaveCircle组件的动画系统通过:

  1. 精确的状态管理
  2. 流畅的动画过渡
  3. 实时的Canvas更新
  4. 优雅的动画联动

实现了一个:

  • 视觉效果出色
  • 性能表现优异
  • 用户体验流畅
  • 可维护性强

的交互动画系统。


全栈若城
1 声望2 粉丝