如何实现球形粒子动画效果
============

#### 问题现象

如何实现一个球形粒子动画的效果？

#### 效果预览

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/0d/v3/o_c50AKBSIWxAg1gKJaezg/zh-cn_image_0000002628554402.gif?HW-CC-KV=V1&HW-CC-Date=20260709T134052Z&HW-CC-Expire=86400&HW-CC-Sign=1FE12E575833F15FD0BE2B3559488FF87129F670DD7A90929900D51ADDDC473C "点击放大")

#### 背景知识

粒子动画是一种通过在一定范围内随机生成的大量粒子的运动来组成的动画效果。在HarmonyOS中，这种动画效果主要通过[Particle](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-particle-animation)组件来实现。

#### 解决方案

1.  通过Stack布局函数构建了一个包含粒子特效的界面。
2.  创建了一个Particle粒子系统，配置了粒子的各种属性，例如粒子的发射率、生命周期、颜色、透明度、缩放、加速度等。
3.  设置了一个扰动场（Disturbance Fields），用于影响粒子的行为。
4.  监听视图区域的变化，并根据新的视图尺寸调整扰动场的大小和位置。

完整示例参考如下：

@Entry
@Component
struct CircleDemo {
  @State viewWidth: number \= 0;
  @State viewHeight: number \= 0;

  build() {
    Stack() {
      Particle({
        particles: \[
          {
            emitter: {
              particle: {
                type: ParticleType.POINT, _//_ _粒子类型_
                config: {
                  radius: 1 _//_ _圆点半径_
                },
                count: -1, _// 粒子总数_
                lifetime: 5000, _// 粒子生命周期，单位ms_
                lifetimeRange: 100 _// 粒子生命周期取值范围，单位ms_
              },
              emitRate: 200, _// 每秒发射粒子数_
              position: \[0, 0\],
              shape: ParticleEmitterShape.CIRCLE _// 发射器形状_
            },
            color: {
              range: \[Color.White, Color.White\] _//_ _初始颜色范围_
            },
            opacity: {
              range: \[0.0, 1.0\], _//_ _粒子透明度的初始值从【0.0到1.0】随机产生_
              updater: {
                type: ParticleUpdater.CURVE, _//_ _透明度的变化方式是随机变化_
                config: \[
                  {
                    from: 0.0,
                    to: 1.0,
                    startMillis: 0,
                    endMillis: 2500,
                    curve: Curve.EaseIn
                  },
                  {
                    from: 1.0,
                    to: 0.0,
                    startMillis: 2500,
                    endMillis: 5000,
                    curve: Curve.EaseIn
                  }
                \]
              }
            },
            scale: {
              range: \[0.0, 0.0\],
              updater: {
                type: ParticleUpdater.CURVE,
                config: \[
                  {
                    from: 0.0,
                    to: 1.0,
                    startMillis: 0,
                    endMillis: 1000,
                    curve: Curve.EaseIn
                  },
                  {
                    from: 1.0,
                    to: 0,
                    startMillis: 1000,
                    endMillis: 5000,
                    curve: Curve.EaseIn
                  }
                \]
              }
            },
            acceleration: {
              _// 加速度的配置，从大小和方向两个维度变化，speed表示加速度大小，angle表示加速度方向_
              speed: {
                range: \[3, 9\],
                updater: {
                  type: ParticleUpdater.RANDOM,
                  config: \[1, 20\]
                }
              },
              angle: {
                range: \[0, 360\]
              }
            },
            spin: {
              range: \[0, 1.0\],
              updater: {
                type: ParticleUpdater.CURVE,
                config: \[
                  {
                    from: 0,
                    to: 180,
                    startMillis: 0,
                    endMillis: 5000,
                    curve: Curve.EaseIn
                  }
                \]
              }
            },
            velocity: {
              speed: \[20, 30\],
              angle: \[0.0, 1.0\]
            }
          }
        \]
      })
        .width('100%')
        .height('100%')
        .backgroundColor(Color.Black)
        .disturbanceFields(\[{
          strength: 80, _// 场强，表示场从中心向外的排斥力的强度，默认值0。正数表示排斥力方向朝外，负数表示吸引力，方向朝内_
          shape: DisturbanceFieldShape.CIRCLE, _// 场的形状_
          size: { width: this.viewWidth, height: this.viewHeight }, _//_ _场的大小_
          position: { x: this.viewWidth / 2, y: this.viewHeight / 2 } _//_ _场的位置_
        }\])
        .onAreaChange((oldValue: Area, newValue: Area) \=\> {
       _   // 监听视图区域的变化，并根据新的视图尺寸调整扰动场的大小和位置_
          this.viewWidth \= newValue.width as number;
          this.viewHeight \= newValue.height as number;
        });
    }
  }
}

#### 总结

Particle组件通过配置多个粒子属性来实现了一个动态的、具有视觉吸引力的粒子动画效果。