Canvas-based particle system that triggers when clicking any href=#tickets button. Uses theme colors, auto-clears when done.
95 lines
2.5 KiB
JavaScript
95 lines
2.5 KiB
JavaScript
(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);
|
|
});
|
|
})(); |