JS实现一个烟花特效效果如下

烟花

js代码如下

window.addEventListener("resize", resizeCanvas, false);
// window.addEventListener("DOMContentLoaded", openFlower, false);
window.requestAnimationFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};

var canvas,
ctx,
w,
h,
particles = [],
probability = 0.99,
xPoint,
yPoint;
function openFlower() {
canvas = document.getElementById("canvas");
if (!canvas) return;
ctx = canvas.getContext("2d");
resizeCanvas();
window.requestAnimationFrame(updateWorld);

// 自动销毁
// setTimeout(() => {
// probability = 0.01
// updateWorld()
// }, 11000)
}

function resizeCanvas() {
if (!!canvas) {
w = canvas.width = 1920;
h = canvas.height = 1080;
}
}

function updateWorld() {
update();
paint();
window.requestAnimationFrame(updateWorld);
}

function update() {
if (particles.length < 500 && Math.random() < probability) {
createFirework();
}
var alive = [];
for (var i = 0; i < particles.length; i++) {
if (particles[i].move()) {
alive.push(particles[i]);
}
}
particles = alive;
}

function paint() {
// 清除画布
ctx.clearRect(0, 0, w, h);
// 绘制透明背景
ctx.fillStyle = "rgba(0, 0, 0, 0)";
ctx.fillRect(0, 0, w, h);
// 设置混合模式
ctx.globalCompositeOperation = "lighter";
// 绘制烟花粒子
for (var i = 0; i < particles.length; i++) {
particles[i].draw(ctx);
}
}

function createFirework() {
xPoint = Math.random() * (w - 200) + 100;
yPoint = Math.random() * (h - 200) + 100;
// xPoint = Math.random() * w;
// yPoint = Math.random() * h;
var nFire = Math.random() * 50 + 100;
var c =
"rgb(" +
~~(Math.random() * 200 + 55) +
"," +
~~(Math.random() * 200 + 55) +
"," +
~~(Math.random() * 200 + 55) +
")";
for (var i = 0; i < nFire; i++) {
var particle = new Particle();
particle.color = c;
var vy = Math.sqrt(25 - particle.vx * particle.vx);
if (Math.abs(particle.vy) > vy) {
particle.vy = particle.vy > 0 ? vy : -vy;
}
particles.push(particle);
}
}

function Particle() {
this.w = this.h = Math.random() * 4 + 1.1;
this.x = xPoint - this.w / 2;
this.y = yPoint - this.h / 2;
this.vx = (Math.random() - 0.5) * 10;
this.vy = (Math.random() - 0.5) * 10;
this.alpha = Math.random() * 0.5 + 0.5;
this.color;
}

Particle.prototype = {
gravity: 0.05,
move: function () {
this.x += this.vx;
this.vy += this.gravity;
this.y += this.vy;
this.alpha -= 0.01;
if (
this.x <= -this.w ||
this.x >= screen.width ||
this.y >= screen.height ||
this.alpha <= 0
) {
return false;
}
return true;
},
draw: function (c) {
c.save();
c.beginPath();
c.translate(this.x + this.w / 2, this.y + this.h / 2);
c.arc(0, 0, this.w, 0, Math.PI * 2);
c.fillStyle = this.color;
c.globalAlpha = this.alpha;
c.closePath();
c.fill();
c.restore();
},
};
openFlower();

整体html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<style>
body {
margin: 0;
overflow: hidden;
background-color: rgba(0, 0, 0, 0.8);
}
</style>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

<script>
window.addEventListener("resize", resizeCanvas, false);
// window.addEventListener("DOMContentLoaded", openFlower, false);
window.requestAnimationFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};

var canvas,
ctx,
w,
h,
particles = [],
probability = 0.99,
xPoint,
yPoint;
function openFlower() {
canvas = document.getElementById("canvas");
if (!canvas) return;
ctx = canvas.getContext("2d");
resizeCanvas();
window.requestAnimationFrame(updateWorld);

// 自动销毁
// setTimeout(() => {
// probability = 0.01
// updateWorld()
// }, 11000)
}

function resizeCanvas() {
if (!!canvas) {
w = canvas.width = 1920;
h = canvas.height = 1080;
}
}

function updateWorld() {
update();
paint();
window.requestAnimationFrame(updateWorld);
}

function update() {
if (particles.length < 500 && Math.random() < probability) {
createFirework();
}
var alive = [];
for (var i = 0; i < particles.length; i++) {
if (particles[i].move()) {
alive.push(particles[i]);
}
}
particles = alive;
}

function paint() {
// 清除画布
ctx.clearRect(0, 0, w, h);
// 绘制透明背景
ctx.fillStyle = "rgba(0, 0, 0, 0)";
ctx.fillRect(0, 0, w, h);
// 设置混合模式
ctx.globalCompositeOperation = "lighter";
// 绘制烟花粒子
for (var i = 0; i < particles.length; i++) {
particles[i].draw(ctx);
}
}

function createFirework() {
xPoint = Math.random() * (w - 200) + 100;
yPoint = Math.random() * (h - 200) + 100;
// xPoint = Math.random() * w;
// yPoint = Math.random() * h;
var nFire = Math.random() * 50 + 100;
var c =
"rgb(" +
~~(Math.random() * 200 + 55) +
"," +
~~(Math.random() * 200 + 55) +
"," +
~~(Math.random() * 200 + 55) +
")";
for (var i = 0; i < nFire; i++) {
var particle = new Particle();
particle.color = c;
var vy = Math.sqrt(25 - particle.vx * particle.vx);
if (Math.abs(particle.vy) > vy) {
particle.vy = particle.vy > 0 ? vy : -vy;
}
particles.push(particle);
}
}

function Particle() {
this.w = this.h = Math.random() * 4 + 1.1;
this.x = xPoint - this.w / 2;
this.y = yPoint - this.h / 2;
this.vx = (Math.random() - 0.5) * 10;
this.vy = (Math.random() - 0.5) * 10;
this.alpha = Math.random() * 0.5 + 0.5;
this.color;
}

Particle.prototype = {
gravity: 0.05,
move: function () {
this.x += this.vx;
this.vy += this.gravity;
this.y += this.vy;
this.alpha -= 0.01;
if (
this.x <= -this.w ||
this.x >= screen.width ||
this.y >= screen.height ||
this.alpha <= 0
) {
return false;
}
return true;
},
draw: function (c) {
c.save();
c.beginPath();
c.translate(this.x + this.w / 2, this.y + this.h / 2);
c.arc(0, 0, this.w, 0, Math.PI * 2);
c.fillStyle = this.color;
c.globalAlpha = this.alpha;
c.closePath();
c.fill();
c.restore();
},
};
openFlower();
</script>