Add fireworks effect on ticket CTA clicks
Canvas-based particle system that triggers when clicking any href=#tickets button. Uses theme colors, auto-clears when done.
This commit is contained in:
parent
dd1855b20e
commit
02ae132a7a
95
js/fireworks.js
Normal file
95
js/fireworks.js
Normal file
@ -0,0 +1,95 @@
|
||||
(function () {
|
||||
var canvas = document.createElement("canvas");
|
||||
var ctx = canvas.getContext("2d");
|
||||
canvas.style.cssText =
|
||||
"position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9999;";
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
var W = (canvas.width = window.innerWidth);
|
||||
var H = (canvas.height = window.innerHeight);
|
||||
|
||||
window.addEventListener("resize", function () {
|
||||
W = canvas.width = window.innerWidth;
|
||||
H = canvas.height = window.innerHeight;
|
||||
});
|
||||
|
||||
var particles = [];
|
||||
var raf = null;
|
||||
var colors = ["#3a6b5e", "#c8a24a", "#e0c068", "#5a9384", "#f5e4cf", "#2d5448"];
|
||||
|
||||
function Particle(x, y, color) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.color = color;
|
||||
var angle = Math.random() * Math.PI * 2;
|
||||
var speed = Math.random() * 6 + 2;
|
||||
this.vx = Math.cos(angle) * speed;
|
||||
this.vy = Math.sin(angle) * speed;
|
||||
this.alpha = 1;
|
||||
this.decay = Math.random() * 0.015 + 0.01;
|
||||
this.size = Math.random() * 3 + 1;
|
||||
}
|
||||
|
||||
Particle.prototype.update = function () {
|
||||
this.x += this.vx;
|
||||
this.y += this.vy;
|
||||
this.vy += 0.08;
|
||||
this.vx *= 0.99;
|
||||
this.vy *= 0.99;
|
||||
this.alpha -= this.decay;
|
||||
};
|
||||
|
||||
Particle.prototype.draw = function () {
|
||||
ctx.globalAlpha = this.alpha;
|
||||
ctx.fillStyle = this.color;
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
};
|
||||
|
||||
function explode(x, y) {
|
||||
for (var i = 0; i < 80; i++) {
|
||||
particles.push(new Particle(x, y, colors[Math.floor(Math.random() * colors.length)]));
|
||||
}
|
||||
if (!raf) loop();
|
||||
}
|
||||
|
||||
function loop() {
|
||||
raf = requestAnimationFrame(loop);
|
||||
ctx.clearRect(0, 0, W, H);
|
||||
for (var i = particles.length - 1; i >= 0; i--) {
|
||||
var p = particles[i];
|
||||
p.update();
|
||||
p.draw();
|
||||
if (p.alpha <= 0) particles.splice(i, 1);
|
||||
}
|
||||
if (particles.length === 0) {
|
||||
cancelAnimationFrame(raf);
|
||||
raf = null;
|
||||
ctx.clearRect(0, 0, W, H);
|
||||
}
|
||||
}
|
||||
|
||||
function handleClick(e) {
|
||||
var x = e.clientX;
|
||||
var y = e.clientY;
|
||||
|
||||
explode(x, y);
|
||||
setTimeout(function () { explode(x - 80, y - 60); }, 120);
|
||||
setTimeout(function () { explode(x + 80, y - 40); }, 240);
|
||||
setTimeout(function () { explode(x, y - 100); }, 360);
|
||||
}
|
||||
|
||||
function isTicketsCTA(el) {
|
||||
if (!el) return false;
|
||||
do {
|
||||
if (el.tagName === "A" && el.getAttribute("href") === "#tickets") return true;
|
||||
el = el.parentElement;
|
||||
} while (el);
|
||||
return false;
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (isTicketsCTA(e.target)) handleClick(e);
|
||||
});
|
||||
})();
|
||||
Loading…
x
Reference in New Issue
Block a user