← back to [single element] CSS Double Helixcompare with ground truth →
model output
Claude Sonnet 4.6
[single element] CSS Double Helix
A 0.88T 0.29
1<!DOCTYPE html>
2<html>
3<head>
4<style>
5 * { margin: 0; padding: 0; box-sizing: border-box; }
6 body { overflow: hidden; width: 100vw; height: 100vh; }
7 canvas { display: block; }
8</style>
9</head>
10<body>
11<canvas id="c"></canvas>
12<script>
13const canvas = document.getElementById('c');
14const ctx = canvas.getContext('2d');
15
16canvas.width = window.innerWidth;
17canvas.height = window.innerHeight;
18
19const W = canvas.width;
20const H = canvas.height;
21
22// Draw gradient background
23function drawBackground() {
24 const grad = ctx.createRadialGradient(W*0.45, H*0.45, 0, W*0.45, H*0.45, W*0.7);
25 grad.addColorStop(0, '#90e040');
26 grad.addColorStop(0.5, '#60a830');
27 grad.addColorStop(1, 'transparent');
28
29 // Base gradient
30 const base = ctx.createLinearGradient(0, 0, W, H);
31 base.addColorStop(0, '#3050c0');
32 base.addColorStop(0.5, '#508030');
33 base.addColorStop(1, '#c04030');
34
35 ctx.fillStyle = base;
36 ctx.fillRect(0, 0, W, H);
37
38 // Green center glow
39 const glow = ctx.createRadialGradient(W*0.42, H*0.5, 0, W*0.42, H*0.5, W*0.35);
40 glow.addColorStop(0, 'rgba(120,220,40,0.7)');
41 glow.addColorStop(1, 'rgba(120,220,40,0)');
42 ctx.fillStyle = glow;
43 ctx.fillRect(0, 0, W, H);
44}
45
46function drawDots(t) {
47 const numDots = 28;
48 const centerY = H * 0.5;
49 const amplitude = 28;
50 const spacing = W / (numDots - 1);
51 const speed = 0.8; // radians per second
52 const wavelength = numDots * 0.5; // dots per full wave
53
54 for (let i = 0; i < numDots; i++) {
55 const x = i * spacing;
56 const phase = (i / wavelength) * Math.PI * 2 - t * speed;
57
58 // Two rows - sine wave
59 const y1 = centerY - amplitude * Math.sin(phase) - 14;
60 const y2 = centerY - amplitude * Math.sin(phase + Math.PI) - 14;
61
62 // Size based on position in wave
63 const s1 = Math.abs(Math.sin(phase));
64 const s2 = Math.abs(Math.sin(phase + Math.PI));
65
66 const r1 = 5 + s1 * 9;
67 const r2 = 5 + s2 * 9;
68
69 ctx.beginPath();
70 ctx.arc(x, y1, r1, 0, Math.PI * 2);
71 ctx.fillStyle = 'white';
72 ctx.fill();
73
74 ctx.beginPath();
75 ctx.arc(x, y2 + 28, r2, 0, Math.PI * 2);
76 ctx.fillStyle = 'white';
77 ctx.fill();
78 }
79}
80
81let startTime = null;
82
83function animate(ts) {
84 if (!startTime) startTime = ts;
85 const t = (ts - startTime) / 1000;
86
87 ctx.clearRect(0, 0, W, H);
88 drawBackground();
89 drawDots(t);
90
91 requestAnimationFrame(animate);
92}
93
94requestAnimationFrame(animate);
95
96window.addEventListener('resize', () => {
97 canvas.width = window.innerWidth;
98 canvas.height = window.innerHeight;
99});
100</script>
101</body>
102</html>