JIT
Grid - Untitled
In one html file create a triple pendulum animation that follows the laws of gravity. No controls, no interactions, simply the animation. Make sure each intercept from one pendulum to another leaves a trail.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Triple Pendulum Animation</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
        background: #0a0a0a;
        overflow: hidden;
        width: 100vw;
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: flex-start;
    }
    
    #pendulum-canvas {
        background: radial-gradient(circle at center, #111, #000);
        display: block;
        width: 100vw;
        height: 100vh;
    }
</style>
</head> <body> <canvas id="pendulum-canvas"></canvas>
<script>
    const canvas = document.getElementById('pendulum-canvas');
    const ctx = canvas.getContext('2d');
    
    function resizeCanvas() {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }
    
    resizeCanvas();
    window.addEventListener('resize', resizeCanvas);
    
    // Triple pendulum parameters
    const g = 9.81; // gravity
    const dt = 0.02; // time step
    
    // Pendulum properties
    const m1 = 10, m2 = 10, m3 = 10; // masses
    const L1 = 150, L2 = 120, L3 = 100; // lengths (scaled for display)
    
    // Initial angles and angular velocities
    let theta1 = Math.PI / 2;
    let theta2 = Math.PI / 2;
    let theta3 = Math.PI / 2;
    let omega1 = 0;
    let omega2 = 0;
    let omega3 = 0;
    
    // Origin point (top of pendulum)
    const originX = canvas.width / 2;
    const originY = 100;
    
    // Trail arrays
    const trail1 = [];
    const trail2 = [];
    const trail3 = [];
    const maxTrailLength = 800;
    
    function calculatePositions() {
        // Position of first pendulum bob
        const x1 = originX + L1 * Math.sin(theta1);
        const y1 = originY + L1 * Math.cos(theta1);
        
        // Position of second pendulum bob
        const x2 = x1 + L2 * Math.sin(theta2);
        const y2 = y1 + L2 * Math.cos(theta2);
        
        // Position of third pendulum bob
        const x3 = x2 + L3 * Math.sin(theta3);
        const y3 = y2 + L3 * Math.cos(theta3);
        
        return { x1, y1, x2, y2, x3, y3 };
    }
    
    function updatePhysics() {
        // Lagrangian mechanics for triple pendulum
        const { x1, y1, x2, y2, x3, y3 } = calculatePositions();
        
        // Simplified physics calculations for triple pendulum
        // (This is a numerical approximation of the complex differential equations)
        
        // Angular accelerations (simplified)
        const alpha1 = (-g * (2 * m1 + m2 + m3) * Math.sin(theta1) - 
                      m2 * g * Math.sin(theta1 - 2 * theta2) - 
                      2 * Math.sin(theta1 - theta2) * m2 * 
                      (omega2 * omega2 * L2 + omega1 * omega1 * L1 * Math.cos(theta1 - theta2))) / 
                     (L1 * (2 * m1 + m2 + m3 - m2 * Math.cos(2 * theta1 - 2 * theta2)));
        
        const alpha2 = (2 * Math.sin(theta1 - theta2) * 
                      (omega1 * omega1 * L1 * (m1 + m2 + m3) + 
                       g * (m1 + m2 + m3) * Math.cos(theta1) + 
                       omega2 * omega2 * L2 * m2 * Math.cos(theta1 - theta2))) / 
                     (L2 * (2 * m1 + m2 + m3 - m2 * Math.cos(2 * theta1 - 2 * theta2)));
        
        const alpha3 = (-g * m3 * Math.sin(theta3) - 
                      0.5 * m3 * (omega1 * omega1 * L1 + omega2 * omega2 * L2) * 
                      Math.sin(theta3 - theta2)) / (L3 * m3);
        
        // Add damping to prevent infinite energy
        const damping = 0.999;
        
        // Update angular velocities
        omega1 += alpha1 * dt;
        omega2 += alpha2 * dt;
        omega3 += alpha3 * dt;
        
        // Apply damping
        omega1 *= damping;
        omega2 *= damping;
        omega3 *= damping;
        
        // Update angles
        theta1 += omega1 * dt;
        theta2 += omega2 * dt;
        theta3 += omega3 * dt;
    }
    
    function addToTrail(trail, x, y) {
        trail.push({ x, y });
        if (trail.length > maxTrailLength) {
            trail.shift();
        }
    }
    
    function drawTrail(trail, color, maxOpacity = 0.8) {
        if (trail.length < 2) return;
        
        for (let i = 1; i < trail.length; i++) {
            const opacity = (i / trail.length) * maxOpacity;
            ctx.strokeStyle = color.replace('1)', `${opacity})`);
            ctx.lineWidth = Math.max(0.5, (i / trail.length) * 3);
            ctx.beginPath();
            ctx.moveTo(trail[i-1].x, trail[i-1].y);
            ctx.lineTo(trail[i].x, trail[i].y);
            ctx.stroke();
        }
    }
    
    function draw() {
        // Fade the canvas instead of clearing it completely for trail effect
        ctx.fillStyle = 'rgba(10, 10, 10, 0.05)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        const { x1, y1, x2, y2, x3, y3 } = calculatePositions();
        
        // Add current positions to trails
        addToTrail(trail1, x1, y1);
        addToTrail(trail2, x2, y2);
        addToTrail(trail3, x3, y3);
        
        // Draw trails
        drawTrail(trail1, 'rgba(255, 100, 100, 1)', 0.6);
        drawTrail(trail2, 'rgba(100, 255, 100, 1)', 0.7);
        drawTrail(trail3, 'rgba(100, 100, 255, 1)', 0.8);
        
        // Draw pendulum rods
        ctx.strokeStyle = '#444';
        ctx.lineWidth = 3;
        
        // Rod 1
        ctx.beginPath();
        ctx.moveTo(originX, originY);
        ctx.lineTo(x1, y1);
        ctx.stroke();
        
        // Rod 2
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
        
        // Rod 3
        ctx.beginPath();
        ctx.moveTo(x2, y2);
        ctx.lineTo(x3, y3);
        ctx.stroke();
        
        // Draw pendulum bobs
        // Bob 1
        ctx.fillStyle = '#ff6464';
        ctx.beginPath();
        ctx.arc(x1, y1, 12, 0, 2 * Math.PI);
        ctx.fill();
        ctx.strokeStyle = '#fff';
        ctx.lineWidth = 2;
        ctx.stroke();
        
        // Bob 2
        ctx.fillStyle = '#64ff64';
        ctx.beginPath();
        ctx.arc(x2, y2, 10, 0, 2 * Math.PI);
        ctx.fill();
        ctx.stroke();
        
        // Bob 3
        ctx.fillStyle = '#6464ff';
        ctx.beginPath();
        ctx.arc(x3, y3, 8, 0, 2 * Math.PI);
        ctx.fill();
        ctx.stroke();
        
        // Draw pivot point
        ctx.fillStyle = '#fff';
        ctx.beginPath();
        ctx.arc(originX, originY, 6, 0, 2 * Math.PI);
        ctx.fill();
    }
    
    function animate() {
        updatePhysics();
        draw();
        requestAnimationFrame(animate);
    }
    
    // Start the animation
    animate();
    
    // Handle window resize
    window.addEventListener('resize', () => {
        resizeCanvas();
        // Clear trails on resize to avoid visual artifacts
        trail1.length = 0;
        trail2.length = 0;
        trail3.length = 0;
    });
</script>
</body> </html>*
Updated files
v1