鸿蒙汽车仪表盘项目-粒子流动
实现了一个动态油量显示组件,其中的粒子效果模拟了液体流动的视觉效果。粒子从底部向上流动,到达顶部后重新从底部出现,形成循环流动的效果。
一,粒子数据结构
首先定义了一个Particle接口来描述每个粒子的基本属性。
- x和y表示粒子位置坐标
- size表示粒子大小
二,粒子初始化
在aboutToAppear生命周期方法中调用generateParticles()方法初始化粒子。
-
使用generateParticles方法生成初始粒子群
-
该方法设置了粒子的X/Y轴所在的位置,以及粒子的大小,并且这是X/Y值和粒子大小的值都是随机的。
确定粒子大小:
- 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}`)
}
最后进行渲染,将每个粒子遍历出来,为每个粒子创建一个圆形视觉元素,这样粒子看起来都是圆的,并设置其大小等等的元素,便可以实现动态粒子的展示。