| Server IP : 103.48.194.25 / Your IP : 216.73.216.74 Web Server : Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.33 System : Linux VMHostDefault 3.10.0-1160.42.2.el7.x86_64 #1 SMP Tue Sep 7 14:49:57 UTC 2021 x86_64 User : sieuthimay ( 1016) PHP Version : 7.4.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/quagiare.com-bk/public_html/skin/js/ |
Upload File : |
// fireworks.js — hiệu ứng pháo hoa
(function() {
// === Thêm CSS động ===
const style = document.createElement("style");
style.textContent = `
.fireworks-canvas {
position: fixed;
inset: 0;
width: 100vw;
height: 100vh;
z-index: 99999;
pointer-events: none;
background: rgba(0,0,0,0.2);
}
`;
document.head.appendChild(style);
// === Hàm gọi pháo hoa chính ===
window.showFireworks = function() {
// tạo canvas
const canvas = document.createElement("canvas");
canvas.className = "fireworks-canvas";
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
let W = canvas.width = innerWidth;
let H = canvas.height = innerHeight;
window.addEventListener("resize", () => {
W = canvas.width = innerWidth;
H = canvas.height = innerHeight;
});
const rand = (min, max) => Math.random() * (max - min) + min;
const randInt = (min, max) => Math.floor(rand(min, max + 1));
class Particle {
constructor(x, y, color, angle, speed, life) {
this.x = x; this.y = y;
this.vx = Math.cos(angle) * speed;
this.vy = Math.sin(angle) * speed;
this.alpha = 1;
this.decay = rand(0.005, 0.02);
this.size = rand(1.2, 3.5);
this.color = color;
this.life = life || 80;
this.age = 0;
}
update() {
this.vy += 0.02;
this.vx *= 0.998; this.vy *= 0.998;
this.x += this.vx; this.y += this.vy;
this.age++;
this.alpha -= this.decay;
if (this.alpha < 0) this.alpha = 0;
}
draw(ctx) {
ctx.save();
ctx.globalCompositeOperation = "lighter";
ctx.globalAlpha = this.alpha;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
alive() { return this.alpha > 0 && this.age < this.life; }
}
class Firework {
constructor(x, y, color, count) {
this.x = x; this.y = y;
this.color = color || `hsl(${randInt(0, 360)},100%,60%)`;
this.particles = [];
this.count = count || randInt(50, 140);
this.spawn();
}
spawn() {
for (let i = 0; i < this.count; i++) {
const angle = rand(0, Math.PI * 2);
const speed = Math.pow(Math.random(), 0.5) * rand(1.5, 6.5);
const life = randInt(60, 140);
const color = `hsl(${randInt(0, 360)},${randInt(70, 100)}%,${randInt(45, 70)}%)`;
this.particles.push(new Particle(this.x, this.y, color, angle, speed, life));
}
}
update() {
this.particles.forEach(p => p.update());
this.particles = this.particles.filter(p => p.alive());
}
draw(ctx) { this.particles.forEach(p => p.draw(ctx)); }
done() { return this.particles.length === 0; }
}
const fireworks = [];
let count = 0, loopId;
function launchAt(x, y) {
const color = `hsl(${randInt(0, 360)},100%,60%)`;
fireworks.push(new Firework(x, y, color, randInt(60, 140)));
count++;
if (count >= 3) {
setTimeout(() => {
cancelAnimationFrame(loopId);
ctx.clearRect(0, 0, W, H);
canvas.remove();
}, 2000);
}
}
function loop() {
loopId = requestAnimationFrame(loop);
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "rgba(0,0,0,0.25)";
ctx.fillRect(0, 0, W, H);
for (let i = fireworks.length - 1; i >= 0; i--) {
const fw = fireworks[i];
fw.update(); fw.draw(ctx);
if (fw.done()) fireworks.splice(i, 1);
}
}
// Khởi động
ctx.fillStyle = "#000"; ctx.fillRect(0, 0, W, H);
loop();
setTimeout(() => launchAt(W * 0.5, H * 0.4), 300);
setTimeout(() => launchAt(W * 0.35, H * 0.45), 1300);
setTimeout(() => launchAt(W * 0.65, H * 0.45), 2300);
};
})();