live - 60fps 1920 x 1080
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Fizzy Sparks</title>
<style>
/*
Fizzy Sparks
------------
This interactive canvas spawns small, glowing sparks wherever the
user moves or clicks the mouse. Each spark travels in a random
direction and fades out over time. The effect approximates the
original CodePen's fizzy sparks animation using only plain
JavaScript and the Canvas API.
*/
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
background: #000;
cursor: crosshair;
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas id="sparks"></canvas>
<script>
(function() {
const canvas = document.getElementById('sparks');
const ctx = canvas.getContext('2d');
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
// Particle class representing a single spark.
class Spark {
constructor(x, y) {
this.x = x;
this.y = y;
const angle= Math.random() * Math.PI * 2;
const speed= 2 + Math.random() * 3;
this.vx = Math.cos(angle) * speed;
this.vy = Math.sin(angle) * speed;
this.life = 40 + Math.floor(Math.random() * 20);
this.age = 0;
this.radius= 2 + Math.random() * 3;
// Choose a bright, random colour.
const hue = Math.floor(Math.random() * 360);
this.colour = `hsl(${hue}, 80%, 60%)`;
}
update() {
this.x += this.vx;
this.y += this.vy;
// Apply a small amount of friction.
this.vx *= 0.98;
this.vy *= 0.98;
// Gravity to pull sparks downwards.
this.vy += 0.05;
this.age++;
}
draw(ctx) {
const alpha = 1 - this.age / this.life;
ctx.fillStyle = this.colour;
ctx.globalAlpha = alpha;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1;
}
isDead() {
return this.age >= this.life;
}
}
const sparks = [];
function spawn(x, y, count) {
for (let i = 0; i < count; i++) {
sparks.push(new Spark(x, y));
}
}
// Spawn sparks on mouse movement and clicks.
let lastSpawn = 0;
document.addEventListener('mousemove', (e) => {
const now = Date.now();
if (now - lastSpawn > 50) {
spawn(e.clientX, e.clientY, 5);
lastSpawn = now;
}
});
document.addEventListener('click', (e) => {
spawn(e.clientX, e.clientY, 20);
});
function animate() {
// Draw a translucent black rectangle to create trails.
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Update and draw each spark.
for (let i = sparks.length - 1; i >= 0; i--) {
const s = sparks[i];
s.update();
s.draw(ctx);
if (s.isDead()) {
sparks.splice(i, 1);
}
}
requestAnimationFrame(animate);
}
animate();
})();
</script>
</body>
</html> About this animation
Rising bubbles and sparks, great for success states.
Under the hood
Upward Buoyancy Physics
Sparks behave with negative gravity (buoyancy). Spawned at the bottom of the screen, they rise upwards, jittering left and right mapped to sine waves, before fading out via
globalAlpha at the top of the viewport. Related