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

model output

GPT-5.4

Only CSS: Pulse Box

A 0.65T 0.29
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" />
6<title>Neon Wireframe Drift</title>
7<style>
8  html, body {
9    margin: 0;
10    width: 100%;
11    height: 100%;
12    overflow: hidden;
13    background: #000;
14  }
15  canvas {
16    display: block;
17    width: 100%;
18    height: 100%;
19    background: #000;
20  }
21</style>
22</head>
23<body>
24<canvas id="c"></canvas>
25<script>
26(() => {
27  const canvas = document.getElementById('c');
28  const ctx = canvas.getContext('2d');
29
30  let w = 0, h = 0, dpr = Math.min(devicePixelRatio || 1, 2);
31
32  function resize() {
33    w = innerWidth;
34    h = innerHeight;
35    canvas.width = Math.round(w * dpr);
36    canvas.height = Math.round(h * dpr);
37    canvas.style.width = w + 'px';
38    canvas.style.height = h + 'px';
39    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
40  }
41  addEventListener('resize', resize);
42  resize();
43
44  const FOV = 700;
45  const SPEED = 260;          // forward camera speed
46  const SPAWN_AHEAD = 4200;
47  const DESPAWN_BEHIND = -300;
48  const COUNT = 54;
49  const COLORS = [
50    [0, 255, 120],   // green
51    [0, 235, 255],   // cyan
52    [0, 40, 255]     // blue
53  ];
54
55  function rand(a, b) { return a + Math.random() * (b - a); }
56  function randi(a, b) { return (a + Math.floor(Math.random() * (b - a + 1))); }
57
58  const shapes = [];
59
60  function makeShape(zBase = rand(300, SPAWN_AHEAD)) {
61    const size = rand(70, 420);
62    const aspect = rand(0.55, 1.8);
63    const ww = size * aspect;
64    const hh = size;
65    const x = rand(-w * 0.9, w * 0.9);
66    const y = rand(-h * 0.9, h * 0.9);
67    const rot = rand(-Math.PI, Math.PI);
68    const tilt = rand(-0.9, 0.9);
69    const spin = rand(-0.18, 0.18);
70    const driftX = rand(-18, 18);
71    const driftY = rand(-18, 18);
72    const stroke = rand(1.2, 3.8);
73    const colorA = COLORS[randi(0, COLORS.length - 1)];
74    const colorB = COLORS[randi(0, COLORS.length - 1)];
75    const alpha = rand(0.65, 1);
76
77    // Mostly open rectangles / bent quads like the reference
78    const mode = Math.random();
79    let pts;
80    if (mode < 0.18) {
81      pts = [
82        [-ww/2, -hh/2], [ww/2, -hh/2], [ww/2, hh/2], [-ww/2, hh/2]
83      ];
84    } else if (mode < 0.55) {
85      pts = [
86        [-ww/2, -hh/2], [ww/2, -hh/2], [-ww/2, hh/2]
87      ];
88    } else {
89      const skew = rand(-ww * 0.35, ww * 0.35);
90      pts = [
91        [-ww/2, -hh/2], [ww/2, -hh/2], [ww/2 + skew * 0.35, hh/2], [-ww/2 + skew, hh/2]
92      ];
93    }
94
95    return {
96      x, y, z: zBase,
97      w: ww, h: hh,
98      rot, tilt, spin,
99      driftX, driftY,
100      stroke, colorA, colorB, alpha,
101      pts,
102      pulse: rand(0, Math.PI * 2),
103      pulseSpeed: rand(0.4, 1.2)
104    };
105  }
106
107  for (let i = 0; i < COUNT; i++) shapes.push(makeShape(rand(200, SPAWN_AHEAD)));
108
109  function project(px, py, pz) {
110    const s = FOV / Math.max(40, pz);
111    return [w * 0.5 + px * s, h * 0.5 + py * s, s];
112  }
113
114  let last = performance.now();
115  let t = 0;
116
117  function drawShape(s, dt) {
118    s.z -= SPEED * dt;
119    s.rot += s.spin * dt;
120    s.x += s.driftX * dt;
121    s.y += s.driftY * dt;
122
123    if (s.z < DESPAWN_BEHIND || Math.abs(s.x) > w * 1.8 || Math.abs(s.y) > h * 1.8) {
124      Object.assign(s, makeShape(SPAWN_AHEAD + rand(0, 1200)));
125      return;
126    }
127
128    const cos = Math.cos(s.rot), sin = Math.sin(s.rot);
129    const pulse = 1 + 0.06 * Math.sin(t * s.pulseSpeed + s.pulse);
130
131    const pts2d = [];
132    for (let i = 0; i < s.pts.length; i++) {
133      let [lx, ly] = s.pts[i];
134      lx *= pulse;
135      ly *= pulse;
136
137      const rx = lx * cos - ly * sin;
138      const ry = lx * sin + ly * cos;
139
140      // fake 3D plane tilt by offsetting z with local y
141      const pz = s.z + ry * s.tilt * 0.9;
142      const [sx, sy, sc] = project(s.x + rx, s.y + ry, pz);
143      pts2d.push([sx, sy, sc]);
144    }
145
146    // subtle trailing ghost
147    ctx.beginPath();
148    for (let i = 0; i < pts2d.length; i++) {
149      const p = pts2d[i];
150      const gx = p[0] - s.driftX * 0.08 - Math.cos(s.rot) * 8;
151      const gy = p[1] - s.driftY * 0.08 + Math.sin(s.rot) * 8;
152      if (i === 0) ctx.moveTo(gx, gy);
153      else ctx.lineTo(gx, gy);
154    }
155    if (s.pts.length === 4 && Math.random() < 0.45) ctx.closePath();
156    ctx.strokeStyle = `rgba(${s.colorA[0]},${s.colorA[1]},${s.colorA[2]},${0.08 * s.alpha})`;
157    ctx.lineWidth = Math.max(0.6, s.stroke * (FOV / Math.max(200, s.z)) * 0.7);
158    ctx.stroke();
159
160    // main stroke with gradient along shape bounds
161    let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
162    for (const p of pts2d) {
163      if (p[0] < minX) minX = p[0];
164      if (p[1] < minY) minY = p[1];
165      if (p[0] > maxX) maxX = p[0];
166      if (p[1] > maxY) maxY = p[1];
167    }
168
169    const grad = ctx.createLinearGradient(minX, minY, maxX, maxY);
170    grad.addColorStop(0, `rgba(${s.colorA[0]},${s.colorA[1]},${s.colorA[2]},${0.95 * s.alpha})`);
171    grad.addColorStop(1, `rgba(${s.colorB[0]},${s.colorB[1]},${s.colorB[2]},${0.95 * s.alpha})`);
172
173    ctx.beginPath();
174    for (let i = 0; i < pts2d.length; i++) {
175      const p = pts2d[i];
176      if (i === 0) ctx.moveTo(p[0], p[1]);
177      else ctx.lineTo(p[0], p[1]);
178    }
179    if (s.pts.length === 4 && Math.random() < 0.35) ctx.closePath();
180
181    const lw = Math.max(0.8, s.stroke * (FOV / Math.max(180, s.z)));
182    ctx.strokeStyle = grad;
183    ctx.lineWidth = lw;
184    ctx.stroke();
185
186    // occasional inner segment like the source frames
187    if (Math.random() < 0.18 && pts2d.length >= 3) {
188      const a = pts2d[0], b = pts2d[2];
189      ctx.beginPath();
190      ctx.moveTo(a[0] * 0.65 + b[0] * 0.35, a[1] * 0.65 + b[1] * 0.35);
191      ctx.lineTo(a[0] * 0.35 + b[0] * 0.65, a[1] * 0.35 + b[1] * 0.65);
192      ctx.strokeStyle = `rgba(${s.colorB[0]},${s.colorB[1]},${s.colorB[2]},${0.35 * s.alpha})`;
193      ctx.lineWidth = lw * 0.55;
194      ctx.stroke();
195    }
196  }
197
198  function frame(now) {
199    const dt = Math.min(0.033, (now - last) / 1000);
200    last = now;
201    t += dt;
202
203    ctx.clearRect(0, 0, w, h);
204    ctx.fillStyle = '#000';
205    ctx.fillRect(0, 0, w, h);
206
207    // slight persistence / glow feel
208    ctx.globalCompositeOperation = 'lighter';
209
210    shapes.sort((a, b) => b.z - a.z);
211    for (const s of shapes) drawShape(s, dt);
212
213    ctx.globalCompositeOperation = 'source-over';
214    requestAnimationFrame(frame);
215  }
216
217  requestAnimationFrame(frame);
218})();
219</script>
220</body>
221</html>