【JS+H5+CSS实现烟花特效】

话不多说直接上代码

注意:背景图路径是picture/star.jpg,自己在同级目录先创键picture目录再下载一张图片命名为star.jpg

HTML:

html 复制代码
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Fireworks Animation</title>
        <link rel="stylesheet" href="style.css" />
    </head>

    <body>
        <canvas id="fireworksCanvas"></canvas>
        <script src="script.js"></script>
    </body>
</html>

JS:

javascript 复制代码
    // 获取canvas元素
    const canvas = document.getElementById('fireworksCanvas');
    const ctx = canvas.getContext('2d');

    // 设置canvas宽度和高度为窗口宽度和高度
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    let fireworks = [];

    // 创建烟花类
    class Firework {
        constructor() {
            this.x = Math.random() * canvas.width; // 随机生成烟花的起始x坐标
            this.y = canvas.height; // 烟花起始y坐标为画布底部
            this.radius = 2; // 烟花半径
            this.speed = 7; // 烟花上升速度
            this.color = 'white'; // 烟花颜色
            this.exploded = false; // 烟花是否已经爆炸
            this.particles = []; // 烟花爆炸后的粒子数组
            this.explosionHeight = Math.random() * (canvas.height * 0.4) + (canvas.height * 0.1); // 生成随机的爆炸高度
            this.initialAlpha = 1; // 初始透明度
            this.currentAlpha = this.initialAlpha; // 当前透明度
        }

        update() {
            if (!this.exploded) {
                this.y -= this.speed; // 烟花向上运动
                // 逐渐减少烟花的透明度
                this.currentAlpha -= 0.005;
                if (this.currentAlpha < 0) {
                    this.currentAlpha = 0;
                }
                if (this.y <= this.explosionHeight) {
                    this.explode();
                }
            } else {
                this.particles.forEach((particle, index) => {
                    particle.update(); // 更新粒子的运动状态
                    if (particle.alpha <= 0) {
                        this.particles.splice(index, 1);
                    }
                });
            }
        }

        draw() {
            ctx.beginPath(); // 开始绘制路径
            ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); // 绘制一个以(x, y)为中心,半径为radius的圆
            ctx.fillStyle = this.color; // 设置填充颜色为烟花的颜色
            ctx.globalAlpha = this.currentAlpha; // 使用当前透明度
            ctx.fill(); // 填充圆
            ctx.closePath(); // 结束绘制路径

            if (this.exploded) {
                this.particles.forEach(particle => {
                    particle.draw(); // 绘制每个粒子
                });
            }
        }

        explode() {
            this.exploded = true; // 设置烟花为已经爆炸状态
            for (let i = 0; i < 100; i++) {
                let particle = new Particle(this.x, this.y); // 创建一个新的粒子,位置为烟花的位置
                this.particles.push(particle); // 将新创建的粒子添加到烟花的粒子数组中
            }
        }
    }

    // 创建粒子类
        class Particle {
        constructor(x, y) { // 粒子类的构造函数,接收x和y坐标作为参数
            this.x = x; // 设置粒子的x坐标
            this.y = y; // 设置粒子的y坐标
            this.radius = 2; // 设置粒子的半径
            this.speedX = Math.random() * 5 - 2; // 随机生成粒子在x轴上的速度
            this.speedY = Math.random() * 5 - 2; // 随机生成粒子在y轴上的速度
            this.color = `hsl(${Math.random() * 360}, 100%, 50%)`; // 随机生成粒子的颜色
            this.alpha = 1.2; // 设置粒子的透明度为1.2
            this.fade = Math.random() * 0.02 + 0.01; // 随机生成粒子透明度的减少速度
        }

        update() { // 更新粒子的位置和透明度
            this.x += this.speedX; // 更新粒子的x坐标
            this.y += this.speedY; // 更新粒子的y坐标
            this.alpha -= this.fade; // 减少粒子的透明度
        }

        draw() { // 绘制粒子
            ctx.beginPath(); // 开始绘制路径
            ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); // 绘制一个以(x, y)为中心,半径为radius的圆
            ctx.fillStyle = this.color; // 设置填充颜色为粒子的颜色
            ctx.globalAlpha = this.alpha; // 设置全局透明度为粒子的透明度
            ctx.fill(); // 填充圆
            ctx.closePath(); // 结束绘制路径
        }
    }

    function animate() { // 动画函数,更新画布内容并绘制烟花和粒子
        ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; // 设置画布背景颜色及透明度
        ctx.fillRect(0, 0, canvas.width, canvas.height); // 填充矩形覆盖画布

        fireworks.forEach((firework, index) => { // 遍历烟花数组
            firework.update(); // 更新烟花的位置和状态
            firework.draw(); // 绘制烟花及其粒子
            if (firework.exploded && firework.particles.length === 0) { // 如果烟花已经爆炸且没有粒子了
                fireworks.splice(index, 1); // 从烟花数组中移除该烟花
            }
        });

        requestAnimationFrame(animate); // 递归调用自身,实现连续动画效果
    }

    function init() { // 初始化函数
        setInterval(() => { // 每隔2秒执行一次
            let firework = new Firework(); // 创建一个新的烟花对象
            fireworks.push(firework); // 将新创建的烟花对象添加到烟花数组中
        }, 100);//每次循环的时间不能太长

        animate(); // 调用动画函数开始动画
    }

    init();

CSS:

css 复制代码
body {
    margin: 0;
    padding: 0;
    overflow: hidden;
    background: url('picture/star.jpg') no-repeat center center fixed;
    background-size: cover;
}
canvas {
    display: block;
    margin: auto;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    opacity: 0.5; /* 设置画布的透明度为0.5 */
}

代码可以直接用。设计思路如下:

1.设计了烟花类,粒子类

2.烟花从上升开始,直到爆炸,爆炸点创建100个粒子对象,粒子用来模拟烟花爆炸后散开的状态

3.烟花和粒子分别拥有初始透明度,经过随机的透明度衰减,达到完全透明,来模拟烟花和粒子的消失

相关推荐
好奇的菜鸟2 分钟前
Go语言中的引用类型:指针与传递机制
开发语言·后端·golang
一条晒干的咸魚2 分钟前
【Web前端】创建我的第一个 Web 表单
服务器·前端·javascript·json·对象·表单
Alive~o.011 分钟前
Go语言进阶&依赖管理
开发语言·后端·golang
花海少爷13 分钟前
第十章 JavaScript的应用课后习题
开发语言·javascript·ecmascript
手握风云-14 分钟前
数据结构(Java版)第二期:包装类和泛型
java·开发语言·数据结构
喵叔哟33 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生39 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
sinat_3842410939 分钟前
在有网络连接的机器上打包 electron 及其依赖项,在没有网络连接的机器上安装这些离线包
javascript·arcgis·electron
hopetomorrow1 小时前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
小牛itbull1 小时前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress