vue3 + canvas 弄一个烟花效果

创建一个简单的烟花效果需要使用 Vue 3 和 Canvas。下面代码与展示效果

<template>
  <div class="wrz_blog-fireworks-container">
    <canvas ref="fireworksCanvas" width="1000" height="1000"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted,watch} from 'vue';

const fireworksCanvas = ref(null);


onMounted(() => {
  const canvas = fireworksCanvas.value;
  const ctx = canvas.getContext("2d");

  // 获取实际显示的宽度和高度
  const displayWidth = canvas.clientWidth;
  const displayHeight = canvas.clientHeight;

  // 设置Canvas元素的实际宽度和高度
  canvas.width = displayWidth;
  canvas.height = displayHeight;

  // 缩放Canvas上下文以适应实际显示尺寸
  ctx.scale(displayWidth / canvas.width, displayHeight / canvas.height);

  const fireworks = [];


  class Particle {
    constructor(x, y, color, velocity, isExplosion = false) {
      this.x = x;
      this.y = y;
      this.color = color;
      this.velocity = velocity;
      this.radius = isExplosion ? 5 : 1; // 调整点的大小
      this.alpha = 1;
      this.isExplosion = isExplosion;
    }

    draw() {
      ctx.globalAlpha = this.alpha;
      ctx.beginPath();
      if (this.isExplosion) {
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
      } else {
        ctx.moveTo(this.x, this.y);
        ctx.lineTo(this.x + this.velocity.x * 5, this.y + this.velocity.y * 5);
        ctx.strokeStyle = this.color;
        ctx.stroke();
      }
      ctx.fillStyle = this.color;
      ctx.fill();
      ctx.globalAlpha = 1;
    }

    update() {
      if (this.isExplosion) {
        this.x += this.velocity.x;
        this.y += this.velocity.y;
        this.radius -= 0.1; // 调整点的变小速度
      } else {
        this.x += this.velocity.x;
        this.y += this.velocity.y;
        this.alpha -= 0.02;
      }
    }
  }

  function createFirework() {
    const x = Math.random() * canvas.width;
    const y = canvas.height;
    const color = getRandomColor();
    const velocity = {
      x: Math.random() * 3 - 1.5,
      y: -Math.random() * 6 - 2,
    };

    const firework = new Particle(x, y, color, velocity);
    fireworks.push(firework);

    // 调整初始线的粗细和颜色
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x + velocity.x * 5, y + velocity.y * 5);
    ctx.strokeStyle = color;
    ctx.lineWidth = 2; // 调整线的粗细
    ctx.stroke();
  }

  function createExplosion(x, y, color) {
    const particles = [];
    const numParticles = Math.random() * 20 + 10;
    for (let i = 0; i < numParticles; i++) {
      const angle = (Math.PI / 15) * i;
      const velocity = {
        x: Math.cos(angle) * (Math.random() * 5 + 2),
        y: Math.sin(angle) * (Math.random() * 5 + 2),
      };
      const isExplosion = Math.random() > 0.5;
      const particleColor = isExplosion ? color : getRandomColor();
      const particle = new Particle(x, y, particleColor, velocity, isExplosion);
      particles.push(particle);
    }
    fireworks.push(particles);
  }

  function getRandomColor() {
    const colors = [
      "#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff", "#ffa500", "#800080",
      "#ff6666", "#66ff66", "#6666ff", "#ffff66", "#ff66ff"
    ];
    return colors[Math.floor(Math.random() * colors.length)];
  }


  function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    if (Math.random() < 0.03) {
      createFirework();
    }

    for (let i = 0; i < fireworks.length; i++) {
      const firework = fireworks[i];

      if (firework instanceof Particle) {
        firework.draw();
        firework.update();

        if (firework.alpha <= 0 || firework.radius <= 0) {
          const { x, y, color } = firework;
          fireworks.splice(i, 1);
          createExplosion(x, y, color);
        }
      } else if (Array.isArray(firework)) {
        for (let j = 0; j < firework.length; j++) {
          const particle = firework[j];
          particle.draw();
          particle.update();
        }

        if (firework.length > 0 && (firework[0].alpha <= 0 || firework[0].radius <= 0)) {
          fireworks.splice(i, 1);
          i--;
        }
      }
    }

    requestAnimationFrame(animate);
  }

  animate();
});


</script>


.wrz_blog-fireworks-container {
    position: fixed;
    bottom: 0;
    left: 0;
    top: -200px;
    height: 100%;
    width: 100%;
    z-index: 0;
    pointer-events: none;
    display: flex;
    justify-content: center;
    align-items: center;
}

.wrz_blog-fireworks-container canvas {
    height: 100%;
    width: 100%;
    display: block;
}

将以上代码直接弄成一个组件 之后再需要的位置引入

  
   import Fireworks from '@/components/fireworks/Fireworks';

	<template>
 	    <Fireworks />
    </template>
    

查看效果

访问王润泽博客 查看
https://wangrunze.com/

  • 41
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值