HarmonyOS 5 高级动效实战:粒子系统、路径动画与物理动效开发

一、粒子系统动画开发

粒子动画通过大量微小元素的运动创造复杂视觉效果,如雨雪、火焰、爆炸等自然现象。

1. 基础粒子系统实现

import particle from '@ohos.graphics.particle';
import { BusinessError } from '@ohos.base';

@Component
struct ParticleAnimationExample {
  @State particles: Array<ParticleData> = [];
  private animationFrame: number = 0;
  private readonly particleCount: number = 100;

  aboutToAppear() {
    this.initParticles();
    this.startAnimation();
  }

  aboutToDisappear() {
    this.stopAnimation();
  }

  // 初始化粒子数据
  private initParticles(): void {
    for (let i = 0; i < this.particleCount; i++) {
      this.particles.push({
        id: i,
        x: Math.random() * 360,
        y: Math.random() * 640,
        size: Math.random() * 5 + 1,
        color: this.getRandomColor(),
        velocityX: (Math.random() - 0.5) * 2,
        velocityY: Math.random() * 3 + 1,
        rotation: Math.random() * 360,
        life: 1.0,
        decay: Math.random() * 0.01 + 0.005
      });
    }
  }

  // 获取随机颜色
  private getRandomColor(): string {
    const colors = ['#FF5252', '#FF4081', '#E040FB', '#7C4DFF', '#536DFE', '#448AFF', '#40C4FF', '#18FFFF'];
    return colors[Math.floor(Math.random() * colors.length)];
  }

  // 启动动画循环
  private startAnimation(): void {
    const animate = () => {
      this.updateParticles();
      this.animationFrame = requestAnimationFrame(animate);
    };
    this.animationFrame = requestAnimationFrame(animate);
  }

  // 停止动画
  private stopAnimation(): void {
    if (this.animationFrame) {
      cancelAnimationFrame(this.AnimationFrame);
    }
  }

  // 更新粒子状态
  private updateParticles(): void {
    for (let i = 0; i < this.particles.length; i++) {
      const particle = this.particles[i];
      
      // 更新位置
      particle.x += particle.velocityX;
      particle.y += particle.velocityY;
      
      // 更新生命周期
      particle.life -= particle.decay;
      
      // 重置死亡粒子
      if (particle.life <= 0 || particle.y > 640) {
        particle.x = Math.random() * 360;
        particle.y = -10;
        particle.life = 1.0;
        particle.velocityX = (Math.random() - 0.5) * 2;
        particle.velocityY = Math.random() * 3 + 1;
      }
    }
  }

  build() {
    Canvas(this.getContext())
      .width('100%')
      .height('100%')
      .onReady(() => {
        this.drawParticles();
      })
  }

  // 绘制粒子
  private drawParticles(): void {
    const context = this.getContext();
    context.clearRect(0, 0, 360, 640);
    
    this.particles.forEach(particle => {
      if (particle.life > 0) {
        context.globalAlpha = particle.life;
        context.beginPath();
        context.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
        context.fillStyle = particle.color;
        context.fill();
      }
    });
    
    context.globalAlpha = 1.0;
  }
}

interface ParticleData {
  id: number;
  x: number;
  y: number;
  size: number;
  color: string;
  velocityX: number;
  velocityY: number;
  rotation: number;
  life: number;
  decay: number;
}

2. 高级粒子发射器

创建可配置的粒子发射器系统:

class ParticleEmitter {
  private particles: ParticleData[] = [];
  private isRunning: boolean = false;
  private emissionRate: number = 10; // 每秒发射粒子数
  private lastEmissionTime: number = 0;

  // 发射器配置
  config: EmitterConfig = {
    position: { x: 180, y: 320 },
    spread: 45, // 发射角度范围
    minVelocity: 1,
    maxVelocity: 5,
    minSize: 1,
    maxSize: 8,
    minLife: 0.5,
    maxLife: 2.0,
    colors: ['#FF5722', '#FF9800', '#FFEB3B', '#4CAF50', '#2196F3'],
    emissionType: 'continuous' // continuous 或 burst
  };

  // 发射粒子
  emit(): void {
    const now = Date.now();
    const elapsed = now - this.lastEmissionTime;
    const particlesToEmit = Math.floor((elapsed / 1000) * this.emissionRate);

    for (let i = 0; i < particlesToEmit; i++) {
      const angle = (Math.random() * this.config.spread - this.config.spread / 2) * Math.PI / 180;
      const velocity = Math.random() * (this.config.maxVelocity - this.config.minVelocity) + this.config.minVelocity;
      
      this.particles.push({
        id: Date.now() + i,
        x: this.config.position.x,
        y: this.config.position.y,
        size: Math.random() * (this.config.maxSize - this.config.minSize) + this.config.minSize,
        color: this.config.colors[Math.floor(Math.random() * this.config.colors.length)],
        velocityX: Math.cos(angle) * velocity,
        velocityY: Math.sin(angle) * velocity,
        rotation: Math.random() * 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值