阅读视图

发现新文章,点击刷新页面。

鸿蒙汽车仪表盘项目-粒子流动

实现了一个动态油量显示组件,其中的粒子效果模拟了液体流动的视觉效果。粒子从底部向上流动,到达顶部后重新从底部出现,形成循环流动的效果。

一,粒子数据结构

首先定义了一个Particle接口来描述每个粒子的基本属性。

  • xy表示粒子位置坐标
  • size表示粒子大小

image.png

二,粒子初始化

在aboutToAppear生命周期方法中调用generateParticles()方法初始化粒子。

  • 使用generateParticles方法生成初始粒子群

  • 该方法设置了粒子的X/Y轴所在的位置,以及粒子的大小,并且这是X/Y值和粒子大小的值都是随机的。

image.png

确定粒子大小:

  • Math.random() * 8 生成 0~8 的随机数。
  • + 8 确保粒子最小为 8px,最大为 16px

粒子在X轴的位置:

  • this.INNER_WIDTH 是容器的宽度(175px)。

  • -16 是因为粒子的大小是 8 + Math.random() * 8(即 8~16px)。

  • 防止粒子溢出:如果粒子大小是 16px,那么它的右边界 x + size 不能超过 INNER_WIDTH,所以最大 x 只能是 INNER_WIDTH - 16

  • this.INNER_LEFT 是容器的左边界偏移量(计算出的内框起始位置)。

  • 保证粒子在容器内

    • 如果直接 Math.random() * INNER_WIDTH,粒子可能超出容器左侧。

    • 加上 INNER_LEFT 确保粒子在正确的区域内生成。

三,粒子动画机制

  • 使用setInterval定时器(约16ms/帧)实现60fps动画

  • 每次更新时创建新数组(遵循ArkUI状态管理规范)

  • 每个粒子以固定速度(flowSpeed)向上移动

  • 当粒子移出顶部边界时,将其重置到底部随机位置

    ```**private** startParticleFlow(): void {  
      **this**.flowSpeed = 1.5;             *//* *设置流动速度*  
      **this**.particleTimer = setInterval(() => {  
        *//* *创建新数组(避免直接修改状态)**  
    ***const** newPositions: Particle[] = [];  
        *//* *遍历并更新每个粒子**  
    ***this**.particlePositions.forEach(particle => {  
          **let** newY = particle.y - **this**.flowSpeed;     *//* *粒子向上移动*  
          **let** newX = particle.x;  
          *//* *当粒子移出顶部时,从底部重新出现**  
    ***if** (newY < **this**.INNER_TOP) {  
            newY = **this**.INNER_TOP + **this**.INNER_HEIGHT - particle.size;  
            newX = Math.random() * (**this**.INNER_WIDTH - particle.size) + **this**.INNER_LEFT;  
          }  
          *//* *显式创建符合接口的新对象**  
    *newPositions.push({  
            x: newX,  
            y: newY,  
            size: particle.size *//* *保持原大小**  
    *});  
        });  
        *//* *更新状态**  
    ***this**.particlePositions = newPositions;  
      }, 16);  
    }
    

四,粒子渲染

使用BuildParticles构建器方法渲染粒子:

```
```@Builder  
BuildParticles() {  
  ForEach(**this**.particlePositions, (item: Particle) => {  
    Circle()  
      .width(item.size)  
      .height(item.size)  
      .borderRadius(50)  
      .position({ x: item.x, y: item.y })  
      .fill('#ffff10fb') *//* *鲜艳的橙红色**  
*.opacity(0.7 + Math.sin(Date.now()/500) * 0.2)  *//* *提高基础透明度**  
*.transition(  
        TransitionEffect.OPACITY  
          .combine(TransitionEffect.scale({ x: 0.8, y: 0.8 })) *//* *使用小写* *scale  
*.animation({  
            duration: 300,  
            curve: Curve.Ease *//* *可选添加缓动曲线**  
*})  
      )  
  }, (item: Particle) => `${item.x}-${item.y}`)  
}

最后进行渲染,将每个粒子遍历出来,为每个粒子创建一个圆形视觉元素,这样粒子看起来都是圆的,并设置其大小等等的元素,便可以实现动态粒子的展示。

❌