animation2code benchmark
For best compatibility, please view this dashboard in a Chrome browser.
← back to Wavy Loading Animations

model output

GPT-5.4

Wavy Loading Animations

A 0.61T 0.21
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>Minimal Dashed Arc Animation</title>
7<style>
8  :root{
9    --bg:#f2f2f2;
10    --dash:#2f2f2f;
11    --dash-fade:#bdbdbd;
12  }
13
14  html,body{
15    margin:0;
16    width:100%;
17    height:100%;
18    overflow:hidden;
19    background:var(--bg);
20  }
21
22  body{
23    display:grid;
24    place-items:center;
25  }
26
27  svg{
28    width:100vw;
29    height:100vh;
30    display:block;
31    background:var(--bg);
32  }
33
34  .trail{
35    fill:none;
36    stroke-linecap:butt;
37    stroke-width:2.2;
38    stroke-dasharray:5 3;
39    vector-effect:non-scaling-stroke;
40  }
41
42  .ghost{
43    stroke:var(--dash-fade);
44    opacity:.9;
45  }
46
47  .main{
48    stroke:var(--dash);
49    opacity:1;
50  }
51</style>
52</head>
53<body>
54<svg viewBox="0 0 1024 768" preserveAspectRatio="none" aria-label="animated dashed line">
55  <defs>
56    <!-- Slightly arched path matching the frames near the top-center -->
57    <path id="arcPath" d="M 484 66 Q 514 48 542 49" pathLength="100"/>
58  </defs>
59
60  <!-- faint previous position -->
61  <use href="#arcPath" class="trail ghost" id="ghostPath"/>
62  <!-- current position -->
63  <use href="#arcPath" class="trail main" id="mainPath"/>
64</svg>
65
66<script>
67  const main = document.getElementById('mainPath');
68  const ghost = document.getElementById('ghostPath');
69
70  // Approximate motion inferred from frames:
71  // starts as a short horizontal dashed segment,
72  // then alternates between a slight upward-arched and downward-sloped pose.
73  const cycle = 1200;
74
75  const poses = [
76    { t: 0.00, x: 0,  y: 0,  r: 0,   len: 60, off: 0 },
77    { t: 0.18, x: 0,  y: 0,  r: -1,  len: 42, off: 8 },
78    { t: 0.36, x: 0,  y: 0,  r: 11,  len: 34, off: 16 },
79    { t: 0.54, x: 0,  y: 0,  r: -1,  len: 42, off: 8 },
80    { t: 0.72, x: 0,  y: 0,  r: 11,  len: 34, off: 16 },
81    { t: 1.00, x: 0,  y: 0,  r: -1,  len: 42, off: 8 }
82  ];
83
84  function lerp(a,b,t){ return a + (b-a)*t; }
85
86  function samplePose(p){
87    let i = 0;
88    while (i < poses.length - 1 && p > poses[i + 1].t) i++;
89    const a = poses[i];
90    const b = poses[Math.min(i + 1, poses.length - 1)];
91    const span = Math.max(0.0001, b.t - a.t);
92    const u = (p - a.t) / span;
93    // smooth easing for soft in-between motion
94    const e = u * u * (3 - 2 * u);
95    return {
96      x: lerp(a.x, b.x, e),
97      y: lerp(a.y, b.y, e),
98      r: lerp(a.r, b.r, e),
99      len: lerp(a.len, b.len, e),
100      off: lerp(a.off, b.off, e)
101    };
102  }
103
104  function apply(el, pose){
105    el.style.transformOrigin = '513px 57px';
106    el.style.transformBox = 'fill-box';
107    el.setAttribute('transform', `translate(${pose.x} ${pose.y}) rotate(${pose.r} 513 57)`);
108    el.style.strokeDashoffset = `${pose.off}px`;
109    // show only a short dashed segment of the path
110    el.style.strokeDasharray = `5 3 ${Math.max(0, pose.len)} 999`;
111  }
112
113  function frame(now){
114    const p = (now % cycle) / cycle;
115    const current = samplePose(p);
116    const previous = samplePose((p - 0.10 + 1) % 1);
117
118    apply(main, current);
119    apply(ghost, previous);
120
121    requestAnimationFrame(frame);
122  }
123
124  requestAnimationFrame(frame);
125</script>
126</body>
127</html>