ArkUI 粒子动画:别只会让卡片平移,光点也能讲氛围

举报
蓝瘦的蜕变 发表于 2026/11/11 22:18:17 2026/11/11
【摘要】 今天我们用 Particle 做一个很轻的点状粒子效果。 粒子动画不是必须做得很夸张。新手一开始更应该先弄明白三个部分:粒子是什么形状、从哪里发射、生命周期里怎么变。这个 Demo 用 ParticleType.POINT,不额外准备图片素材,省事也更聚焦。 这个 Demo 看什么 页面中间是一块深蓝色舞台。Parti

ArkUI 粒子动画:别只会让卡片平移,光点也能讲氛围

今天我们用 Particle 做一个很轻的点状粒子效果。

粒子动画不是必须做得很夸张。新手一开始更应该先弄明白三个部分:粒子是什么形状、从哪里发射、生命周期里怎么变。这个 Demo 用 ParticleType.POINT,不额外准备图片素材,省事也更聚焦。

这个 Demo 看什么

页面中间是一块深蓝色舞台。Particle({ particles: [...] }) 里只有一组点状粒子:

  • emitter.particle 决定粒子类型和半径。
  • emitRate 控制每秒发射数量。
  • ParticleEmitterShape.RECTANGLE 控制发射区域。
  • color、opacity、scale 配合 ParticleUpdater.CURVE 控制粒子生命周期变化。
  • velocity 控制粒子往哪个方向散开。

按钮只切换发射密度。我们不在这里做复杂特效编辑器,先把最小结构跑通。

你在项目里会把粒子用在哪?成功反馈、背景氛围,还是节日活动页?可以从最小效果开始试,不要一上来就堆满屏。

完整代码

@Entry
@Component
struct ArkUIParticleAnimationDemo {
  @State strongMode: boolean = false;

  @Builder
  HeaderBlock() {
    Column({ space: 8 }) {
      Text('ArkUI 粒子动画')
        .fontSize(28)
        .fontWeight(700)
        .fontColor('#111827')
      Text('别只会让卡片平移,光点也能讲氛围')
        .fontSize(16)
        .fontColor('#4B5563')
      Text('这一页只做一个轻量点状粒子:发射器控制粒子从哪里出来,颜色、透明度和缩放更新控制它怎么消失。')
        .fontSize(14)
        .fontColor('#6B7280')
        .lineHeight(22)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  ParticleStage() {
    Stack() {
      Column({ space: 8 }) {
        Text(this.strongMode ? '庆祝反馈' : '轻量氛围')
          .fontSize(22)
          .fontWeight(700)
          .fontColor('#FFFFFF')
        Text(this.strongMode ? '提高 emitRate 后,点状粒子更密。' : '默认状态下,让背景轻轻动起来。')
          .fontSize(13)
          .fontColor('#DBEAFE')
      }
      .alignItems(HorizontalAlign.Center)
      .zIndex(2)

      Particle({
        particles: [
          {
            emitter: {
              particle: {
                type: ParticleType.POINT,
                config: {
                  radius: 4
                },
                count: 80,
                lifetime: 1400
              },
              emitRate: this.strongMode ? 42 : 18,
              shape: ParticleEmitterShape.RECTANGLE,
              position: [0, 0],
              size: ['100%', '100%']
            },
            color: {
              range: ['#FFFFFF', '#93C5FD'],
              updater: {
                type: ParticleUpdater.CURVE,
                config: [
                  { from: '#FFFFFF', to: '#60A5FA', startMillis: 0, endMillis: 900, curve: Curve.EaseOut }
                ]
              }
            },
            opacity: {
              range: [0.35, 0.95],
              updater: {
                type: ParticleUpdater.CURVE,
                config: [
                  { from: 0.95, to: 0, startMillis: 200, endMillis: 1400, curve: Curve.EaseIn }
                ]
              }
            },
            scale: {
              range: [0.6, 1.2],
              updater: {
                type: ParticleUpdater.CURVE,
                config: [
                  { from: 0.7, to: 1.35, startMillis: 0, endMillis: 1200, curve: Curve.EaseOut }
                ]
              }
            },
            velocity: {
              speed: [24, 76],
              angle: [235, 305]
            }
          }
        ]
      })
        .width('100%')
        .height('100%')
        .zIndex(1)
    }
    .width('100%')
    .height(220)
    .borderRadius(22)
    .backgroundColor('#1D4ED8')
    .clip(true)
  }

  build() {
    Scroll() {
      Column({ space: 20 }) {
        this.HeaderBlock()
        this.ParticleStage()

        Button(this.strongMode ? '切回轻量粒子' : '提高发射密度')
          .height(42)
          .fontSize(14)
          .fontColor('#FFFFFF')
          .backgroundColor('#111827')
          .borderRadius(21)
          .padding({ left: 18, right: 18 })
          .onClick(() => {
            this.strongMode = !this.strongMode;
          })

        Column({ space: 8 }) {
          Text('这几个参数先记住')
            .fontSize(18)
            .fontWeight(700)
            .fontColor('#111827')
          Text('ParticleType.POINT 决定粒子形状,ParticleEmitterShape.RECTANGLE 决定发射范围,ParticleUpdater.CURVE 让颜色、透明度和缩放随着时间变化。')
            .fontSize(14)
            .fontColor('#4B5563')
            .lineHeight(22)
        }
        .width('100%')
        .padding(16)
        .borderRadius(16)
        .backgroundColor('#F8FAFC')
        .border({ width: 1, color: '#E5E7EB' })
        .alignItems(HorizontalAlign.Start)
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。