Pendulum Painting
by Ben Gillbanks
HTML
<input type="color" id="colorPicker" value="#000000">
<canvas id="canvas"></canvas>
CSS
body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
canvas { border: 1px solid #ccc; }
input {
position: absolute;
top:0;
left: 0;
z-index:10;
}
JavaScript
document.addEventListener('DOMContentLoaded', () => {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
if (!canvas || !ctx) {
console.error('Canvas or context not supported.');
return;
}
const velocityScale = 0.3;
const velocityThreshold = 0.5;
const maxLineWidth = 15;
const damping = 0.9997;
const gravity = 0.1;
const SPLATTER_CHANCE = 0.95;
const DRIP_CHANCE = 0.9;
const MOVEMENT_TIMEOUT = 10;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
let painting = false;
let startX = 0, startY = 0, velocityX = 0, velocityY = 0, lastX = 0, lastY = 0;
canvas.addEventListener('mousedown', e => {
startX = e.clientX;
startY = e.clientY;
lastX = startX;
lastY = startY;
painting = true;
velocityX = 0;
velocityY = 0;
});
let moveTimer;
canvas.addEventListener('mousemove', e => {
clearTimeout(moveTimer);
moveTimer = setTimeout(() => {
if (painting) {
velocityX = (e.clientX - lastX) * velocityScale;
velocityY = (e.clientY - lastY) * velocityScale;
lastX = e.clientX;
lastY = e.clientY;
}
}, MOVEMENT_TIMEOUT);
});
canvas.addEventListener('mouseup', () => {
painting = false;
simulatePendulumMovement(lastX, lastY, velocityX, velocityY, document.getElementById('colorPicker').value);
});
function simulatePendulumMovement(x, y, vx, vy, color) {
function draw() {
requestAnimationFrame(draw);
if (Math.sqrt(vx * vx + vy * vy) > velocityThreshold) {
vx *= damping;
vy *= damping;
if (Math.random()...