Skip to content

Instantly share code, notes, and snippets.

@goldenratio
Created April 12, 2025 10:23
Show Gist options
  • Save goldenratio/b795ba376a90bc368049fac7c8517e12 to your computer and use it in GitHub Desktop.
Save goldenratio/b795ba376a90bc368049fac7c8517e12 to your computer and use it in GitHub Desktop.
some canvas ball animation
window['playAnimation'] = (options = {}) => {
const { ballCount = 4, onClose = () => { } } = options;
const root = document.getElementById('root');
// Style root to center contents
root.style.display = 'flex';
root.style.justifyContent = 'center';
root.style.alignItems = 'center';
root.style.height = '100vh';
root.style.boxSizing = 'border-box';
root.style.margin = '0';
// Create wrapper container for canvas + button
const wrapper = document.createElement('div');
wrapper.setAttribute('id', 'animation-wrapper');
wrapper.style.display = 'flex';
wrapper.style.flexDirection = 'column';
wrapper.style.alignItems = 'center';
wrapper.style.gap = '16px';
wrapper.style.width = '100%';
wrapper.style.maxWidth = '600px';
wrapper.style.boxSizing = 'border-box';
// Create canvas
const canvas = document.createElement('canvas');
canvas.setAttribute('id', 'animation-canvas');
canvas.width = 600;
canvas.height = 300;
canvas.style.width = '100%';
canvas.style.height = 'auto';
canvas.style.backgroundColor = 'transparent';
wrapper.append(canvas);
// Create close button
const closeBtn = document.createElement('button');
closeBtn.textContent = 'I\'m Feeling Lucky!';
closeBtn.style.padding = '8px 16px';
closeBtn.style.cursor = 'pointer';
wrapper.append(closeBtn);
root.append(wrapper);
// events
closeBtn.addEventListener('click', () => {
window['playAnimation'] = null;
onClose();
});
const context = canvas.getContext("2d");
//create te container that will hold the bouncing balls.
const container = {
x: 0,
y: 0,
width: canvas.width,
height: canvas.height
};
// Generate random circles
const circles = Array.from({ length: ballCount }, () => ({
x: Math.random() * (container.width - 40) + 20,
y: Math.random() * (container.height - 40) + 20,
r: Math.random() * 15 + 5,
vx: (Math.random() - 0.5) * 20,
vy: (Math.random() - 0.5) * 20,
color: Math.floor(Math.random() * 360)
}));
function animate() {
context.clearRect(container.x, container.y, container.width, container.height);
for (var i = 0; i < circles.length; i++) {
context.fillStyle = 'hsl(' + circles[i].color++ + ', 100%, 50%)';
context.beginPath();
context.arc(circles[i].x, circles[i].y, circles[i].r, 0, Math.PI * 2, true);
context.fill()
if (circles[i].x - circles[i].r + circles[i].vx < container.x || circles[i].x + circles[i].r + circles[i].vx > container.x + container.width) {
circles[i].vx = -circles[i].vx;
}
if (circles[i].y + circles[i].r + circles[i].vy > container.y + container.height || circles[i].y - circles[i].r + circles[i].vy < container.y) {
circles[i].vy = -circles[i].vy;
}
circles[i].x += circles[i].vx
circles[i].y += circles[i].vy
}
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment