animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to Only CSS: Peacock

model output

Gemini 3 Flash Preview

Only CSS: Peacock

A 0.56T 0.24
compare with ground truth →
1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <title>Spiraling Sawblade Animation</title>
7    <style>
8        body {
9            margin: 0;
10            padding: 0;
11            background-color: #000;
12            overflow: hidden;
13            display: flex;
14            justify-content: center;
15            align-items: center;
16            height: 100vh;
17        }
18        canvas {
19            display: block;
20        }
21    </style>
22</head>
23<body>
24    <canvas id="canvas"></canvas>
25
26    <script>
27        const canvas = document.getElementById('canvas');
28        const ctx = canvas.getContext('2d');
29
30        let width, height, cx, cy;
31        let startTime = null;
32        const duration = 4000; // Total animation loop duration in ms
33        const spiralStart = 1500; // When the spiral starts expanding
34        const totalSegments = 160; // Number of overlapping shapes in the trail
35
36        function resize() {
37            width = canvas.width = window.innerWidth;
38            height = canvas.height = window.innerHeight;
39            cx = width / 2;
40            cy = height / 2;
41        }
42
43        window.addEventListener('resize', resize);
44        resize();
45
46        /**
47         * Draws the specific "sawblade" quadrant shape seen in the video.
48         * The shape consists of 4 quadrants, each with serrated edges.
49         */
50        function drawSawblade(x, y, radius, color, rotation) {
51            ctx.save();
52            ctx.translate(x, y);
53            ctx.rotate(rotation);
54            ctx.fillStyle = color;
55            
56            for (let q = 0; q < 4; q++) {
57                ctx.save();
58                ctx.rotate(q * Math.PI / 2);
59                ctx.beginPath();
60                ctx.moveTo(0, 0);
61                
62                // Draw serrated quadrant edge
63                const teeth = 8;
64                const angleStep = (Math.PI / 2) / teeth;
65                for (let i = 0; i <= teeth; i++) {
66                    const angle = i * angleStep;
67                    // Alternating radius creates the "shredded" look
68                    const r = (i % 2 === 0) ? radius : radius * 0.4;
69                    ctx.lineTo(Math.cos(angle) * r, Math.sin(angle) * r);
70                }
71                
72                ctx.closePath();
73                ctx.fill();
74                ctx.restore();
75            }
76            ctx.restore();
77        }
78
79        function animate(timestamp) {
80            if (!startTime) startTime = timestamp;
81            let elapsed = (timestamp - startTime) % duration;
82
83            ctx.clearRect(0, 0, width, height);
84
85            // Overall rotation speed (constant throughout)
86            const globalRotation = (elapsed / 1000) * Math.PI * 1.5;
87
88            if (elapsed < spiralStart) {
89                // Phase 1: Rotating in center (0s - 1.5s)
90                drawSawblade(cx, cy, 35, '#ff0000', globalRotation);
91            } else {
92                // Phase 2: Spiraling out (1.5s - 4.0s)
93                const spiralProgress = (elapsed - spiralStart) / (duration - spiralStart);
94                
95                // We draw the trail up to the current progress point
96                const visibleCount = Math.floor(spiralProgress * totalSegments);
97
98                for (let i = 0; i <= visibleCount; i++) {
99                    const p = i / totalSegments;
100                    
101                    // Spiral parameters: radius grows and angle rotates
102                    // Math.pow(p, 1.2) adds a slight acceleration to the expansion
103                    const radius = Math.pow(p, 1.2) * (Math.min(width, height) * 0.4);
104                    const spiralAngle = p * Math.PI * 2.8; // Approx 1.4 turns
105                    
106                    // Starting direction (pointing upwards at 1.5s mark)
107                    const startOffset = -Math.PI / 2;
108                    
109                    const x = cx + radius * Math.cos(spiralAngle + startOffset + globalRotation);
110                    const y = cy + radius * Math.sin(spiralAngle + startOffset + globalRotation);
111
112                    // Color transition: Red -> Magenta -> Purple -> Blue
113                    // Red is hue 0, Blue is hue 240-270
114                    const hue = p * 270;
115                    const color = `hsl(${hue}, 100%, 50%)`;
116
117                    // Subtle fade-in for each segment as it appears
118                    ctx.globalAlpha = i === visibleCount ? (spiralProgress * totalSegments % 1) : 1;
119                    
120                    // The individual shape rotates with the system
121                    drawSawblade(x, y, 35, color, globalRotation + spiralAngle);
122                }
123                ctx.globalAlpha = 1;
124            }
125
126            requestAnimationFrame(animate);
127        }
128
129        requestAnimationFrame(animate);
130    </script>
131</body>
132</html>