切换前把当前 emitRate 缓慢插值到 0,切模式后再缓慢插回目标值(避免瞬间粒子激增)。count 不要过大、lifetime 尽量不要设 -1(无限),并给 lifetimeRange 做离散。下面示例演示完整过程与防炸帧配置。type Mode = 'point' | 'image'; @Entry @Component struct SafeTypeSwitch { @State mode: Mode = 'point'; @State liveRate: number = 160; // 实时发射率 private targetRate = 160; private timer: number | null = null; // 线性插值发射率,避免骤变 private tweenEmit(to: number, stepMs: number = 40) { if (this.timer) { clearInterval(this.timer as any); this.timer = null; } this.timer = setInterval(() => { const step = (to - this.liveRate) * 0.25; if (Math.abs(step) < 1) { this.liveRate = to; clearInterval(this.timer as any); this.timer = null; } else { this.liveRate += step; } }, stepMs) as any; } private particleOptions(): Particles<ParticleType, ParticleUpdater, ParticleUpdater, ParticleUpdater, ParticleUpdater, ParticleUpdater, ParticleUpdater> { const cfg = this.mode === 'point' ? { type: ParticleType.POINT, config: { radius: 2 }, count: 700, lifetime: 5000, lifetimeRange: 1500 } : { type: ParticleType.IMAGE, config: { src: $r('app.media.icon'), size: [8, 8] }, count: 700, lifetime: 5000, lifetimeRange: 1500 }; return { particles: [{ emitter: { particle: cfg as any, emitRate: this.liveRate, shape: ParticleEmitterShape.RECTANGLE }, color: { range: [Color.White, Color.White] }, // 图片粒子不调整颜色;点粒子纯白 opacity: { range: [0.5, 1.0] }, scale: this.mode === 'point' ? { range: [0.9, 1.2] } : { range: [0.9, 1.4] }, velocity: { speed: [60, 120], angle: [0, 360] } }] } as any; } private switchMode() { // 1) 先把 emitRate 平滑降到 0 this.tweenEmit(0); // 2) 250ms 后切模式(避免正好在峰值期切换) setTimeout(() => { this.mode = this.mode === 'point' ? 'image' : 'point'; // 3) 再把 emitRate 平滑升回目标 this.tweenEmit(this.targetRate); }, 250); } build() { Column({ space: 10 }) { Particle(this.particleOptions()) .width(320).height(200).backgroundColor(0x101214) Row({ space: 8 }) { Text(`当前:${this.mode === 'point' ? 'POINT' : 'IMAGE'}`) Button('平滑切换').onClick(() => this.switchMode()) } // 提醒:count 不要太大、lifetime 避免 -1(无限),并设置 lifetimeRange Text('建议:count ≤ 1000,lifetime≠-1,使用 lifetimeRange 离散粒子生命。') .fontColor(0xB0FFFFFF).fontSize(12) } .padding(12) } }
切换前把当前 emitRate 缓慢插值到 0,切模式后再缓慢插回目标值(避免瞬间粒子激增)。count 不要过大、lifetime 尽量不要设 -1(无限),并给 lifetimeRange 做离散。下面示例演示完整过程与防炸帧配置。