HarmonyOS鸿蒙Next中如何实现呼吸灯动画效果?

HarmonyOS鸿蒙Next中如何实现呼吸灯动画效果? 如何实现呼吸灯动画效果?

3 回复

效果

图片

实现思路

  1. 完成页面布局
  2. Circle组件增加scale属性
  3. 点击事件后,通过animateTo更改scale属性响应式数据值

完整代码

@Builder
export function MainPageBuilder() { // 细节2:按照这个格式配置
  Listen()
}

@Component
struct Listen {
  @StorageProp('bottomRectHeight') bottomRectHeight: number = 0;
  @StorageProp('topRectHeight') topRectHeight: number = 0;
  @State isRecognize: boolean = false
  @State circleScaleIn: number = 1
  @State circleScaleOut: number = 1
  @Consume navPathStack: NavPathStack

  build() {
    NavDestination() {
      Column() {
        Row() {
          Image($r('app.media.ai_listen_left')).width(30).margin({ left: 10 })
          Text('听歌识曲').fontSize(16).fontWeight(600)
          Image($r('app.media.ai_listen_gd')).width(30).margin({ right: 10 })
        }
        .width('100%')
        .justifyContent(FlexAlign.SpaceBetween)
        .onClick(() => this.navPathStack.pushPathByName('AiListen', null))

        Row() {
          Text('开启桌面悬浮球,边刷视频边识曲').fontColor(Color.Gray).margin({ left: 20 })
          Toggle({ type: ToggleType.Switch, isOn: false })
            .selectedColor('#007DFF')
            .switchPointColor('#FFFFFF')
            .onChange((isOn: boolean) => {
              console.info('Component status:' + isOn)
            }).margin({ right: 20 })
        }
        .backgroundColor('#d9e8fc')
        .justifyContent(FlexAlign.SpaceBetween)
        .width('100%')
        .height(40)
        .margin({ top: 10, bottom: 20 })

        Column({ space: 40 }) {
          Stack() {
            Circle({ width: 200, height: 200 })
              .stroke('#dce9fb')
              .strokeWidth(30)
              .fill('none')
              .scale({ x: this.circleScaleOut, y: this.circleScaleOut })
            Circle({ width: 200, height: 200 })
              .fill(this.isRecognize ? '#0783ff' : '#c1dbfc')
              .scale({ x: this.circleScaleIn, y: this.circleScaleIn })

            Image(this.isRecognize ? $r('app.media.ai_listen_logo_white') : $r('app.media.logo'))
              .width(150)
              .padding(15)
              .borderRadius('50%')
              .onClick(async () => {
                // 特效
                this.isRecognize = !this.isRecognize
                if (this.isRecognize) {
                  animateTo({ duration: 500, iterations: -1, playMode: PlayMode.Alternate }, () => {
                    this.circleScaleIn = 0.85
                  })
                  animateTo({ duration: 1000, iterations: -1, curve: Curve.EaseInOut }, () => {
                    this.circleScaleOut = 0.85
                  })
                } else {
                  animateTo({ duration: 0 }, () => {
                    this.circleScaleIn = 1
                    this.circleScaleOut = 1
                  })
                }

              })
          }

          Text('点击开始识曲')
            .fontWeight(700)
            .fontSize(19)
            .fontColor('#575757')
        }.margin({ top: 40, bottom: 230 }).alignItems(HorizontalAlign.Center)

        Row() {
          Text('听歌识曲榜')
            .border({ width: { right: 2 }, color: Color.Gray })
            .width(100)
            .margin({ right: 15, left: 20 })
            .fontColor('#4487f5')
            .fontWeight(700)
          Text('第57次取消发送-菲菲公主')
            .fontColor(Color.Gray)
            .fontSize(14)
            .textOverflow({ overflow: TextOverflow.Ellipsis })
            .maxLines(1)
            .width(160)
          Image($r('app.media.ai_listen_chevron_right'))
            .fillColor(Color.Gray)
            .width(10)
            .margin({ right: 10 })
        }.backgroundColor('#f3f4fc').height(40).borderRadius(30).width('90%')

      }.padding({ top: px2vp(this.topRectHeight) })
      .linearGradient({ direction: GradientDirection.Bottom, colors: [['#d7e7ff', 0], ['#fff', 0.6]] })

    }.hideTitleBar(true)
  }
}

更多关于HarmonyOS鸿蒙Next中如何实现呼吸灯动画效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,实现呼吸灯动画效果主要使用ArkTS的动画API。通过animateTo方法或属性动画,改变组件的透明度(opacity)或缩放比例(scale),并设置curveCurves.EaseInOut来模拟呼吸的平滑节奏。关键是在动画配置中循环播放(设置iterations为-1)并交替反向(设置alternate为true),即可实现明暗循环变化的呼吸效果。

在HarmonyOS Next中,实现呼吸灯动画效果的核心是使用ArkUI的动画API,特别是属性动画。以下是两种主流且简洁的实现方案:

方案一:使用显式动画(animateTo)

这是最直接的方法,通过animateTo函数控制组件的透明度(opacity)或尺寸(scale)等属性,在两种状态间循环过渡,模拟呼吸效果。

示例代码(基于ArkTS):

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

@Entry
@Component
struct BreathLightDemo {
  @State opacityValue: number = 0.2; // 初始透明度

  build() {
    Column() {
      // 需要呼吸的组件,例如一个圆形灯
      Circle({ width: 100, height: 100 })
        .fill(Color.Red)
        .opacity(this.opacityValue) // 绑定透明度
        .onClick(() => {
          this.startBreathAnimation();
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  // 启动呼吸动画
  private startBreathAnimation() {
    // 从暗到亮(透明度增加)
    animateTo({
      duration: 1000, // 动画时长1秒
      curve: Curve.EaseInOut, // 缓动曲线使过渡更自然
      iterations: -1, // 无限循环
      playMode: PlayMode.Alternate // 交替反向播放
    }, () => {
      this.opacityValue = 1.0; // 目标透明度
    });
  }
}

关键点:

  • iterations: -1 设置动画无限循环。
  • playMode: PlayMode.Alternate 使动画在起点和终点间自动往返,形成“呼吸”节奏。
  • 通过调整durationcurve可控制呼吸速度和平滑度。

方案二:使用属性动画(animation)

通过组件的animation方法定义属性动画,实现更精细的控制。

示例代码:

@Entry
@Component
struct BreathLightDemo2 {
  @State scaleValue: number = 0.8;

  build() {
    Column() {
      Circle({ width: 100, height: 100 })
        .fill(Color.Blue)
        .scale({ x: this.scaleValue, y: this.scaleValue }) // 绑定缩放属性
        .animation({
          duration: 1500,
          curve: Curve.EaseInOut,
          iterations: -1,
          playMode: PlayMode.Alternate
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .onClick(() => {
      // 点击触发状态改变,动画自动执行
      this.scaleValue = this.scaleValue === 0.8 ? 1.2 : 0.8;
    })
  }
}

关键点:

  • animation修饰符直接附加到组件,当绑定的状态变量(如scaleValue)变化时自动触发动画。
  • 可通过修改scale(缩放)或opacity(透明度)等属性实现不同视觉效果。

方案选择建议

  • 简单场景:使用方案一(animateTo),代码控制逻辑更集中。
  • 复杂交互:使用方案二(animation),将动画声明与组件绑定,响应状态变化更灵活。

两种方案均能高效实现平滑的呼吸灯效果,且性能开销低。可根据具体UI交互需求选择。

回到顶部