6 number counter animations. Copy any short prompt for free, and open full prompt 1 to see how detailed they are. Full prompts 2–6 are in the pack.
Basics: stage 470×222px, background #13131C, all coordinates in px from the stage's top-left, everything clipped to the stage (top corners rounded 40px). The animation is a 4s loop that plays by itself and is seamless; the video is 12s = three loops. T = seconds since the video start; u = (T + 0.25) mod 4 (the first frame is already 0.25s after a tap). A tap every second: at u = 0, 1, 2, 3 (video T = 0.75, 1.75, 2.75 …). tapInfo(u): k = floor(u) (0–3), dt = u − k (seconds since the last tap, 0–1), from = k, to = (k+1) mod 4, up = VALS[to] > VALS[from]. States: DAYS = Mon, Tue, Wed, Thu; VALS = 6482, 9105, 7348, 8917 (so Mon→Tue up, Tue→Wed down, Wed→Thu up, Thu→Mon down). Format with a thousands comma: "6,482" (always 1 digit, comma, 3 digits; characters 0–4, digits at 0, 2, 3, 4). The card (identical in all six). Draw order: (1) segmented control (2) "steps" (3) goal bar (4) the big number (type-specific), then the tap indicator last. (1) Segmented control rr(40, 24, 390, 46, radius 23) filled #1C1B2B, 2px stroke #3A3852; 4 segments of width 97.5. Selection pill: p = clamp(lerp(from, to, springF(20, 0.72)(dt)), 0, 3); pill rr(44 + 97.5p, 28, 89.5, 38, radius 19) filled with a horizontal gradient #6E5BFF → #38C6FF across the pill, shadow rgba(110,91,255,0.45) blur 12. Labels Mon/Tue/Wed/Thu centered at x = 40 + 97.5(j + 0.5), baseline 54.5, font 700 21px "Segoe UI Variable Display","Segoe UI",sans-serif, color mix(#8D8AAE, #FFFFFF, clamp(1 − |p − j|)). Big number: font 800 100px same family, color #F4F4F8, alphabetic baseline y 166. Fixed columns (no layout shift): DW = width of "0" (≈57.5px), CW = width of "," (≈26.1px), UW = width of "steps" in 600 26px (≈63.2px). Measure them with ctx.measureText in the digit font (800 100px) after document.fonts.load() resolves; the ≈ values are only what Segoe UI Variable Display gives — always use the measured values. group width 4DW + CW + 12 + UW; x0 = 235 − groupWidth/2 (≈69.3); character left edges: x0, x0+DW, x0+DW+CW, x0+2DW+CW, x0+3DW+CW. Each digit is centred in its DW column (draw at x + (DW − its own advance)/2), like tabular figures. Digit middle line DMID = 130 (baseline − 36). (2) "steps" in 600 26px #8D8AAE, left at x0 + 4DW + CW + 12, baseline 166. (3) Goal bar: track rr(40, 193, 390, 8, radius 4) #2A2840; fill width max(8, 390·clamp(lerp(VALS[from], VALS[to], springF(14, 0.8)(dt))/10000)), same rect, horizontal gradient #6E5BFF → #38C6FF from x 40 to 430. Glyph sprites (important, so moving digits glide smoothly instead of stepping 1px): after the fonts load, draw each character 0–9 and "," once into its own small offscreen canvas in each color. Sprite width = ceil(DW) + 28 for every digit (also "1", which is narrower in this font) and ceil(CW) + 28 for the comma; height 150; the character is drawn at x = 14 + (column width − its own advance)/2 (column width DW for digits, CW for the comma), baseline 118, so it is centred in its column. Colors: white #F4F4F8, shade #4A4866, mint #3DDBB0, pink #FF5CA8, light cyan #9FE4FF, and a vertical gradient #8F7BFF (y 44) → #38C6FF (y 118). glyph(ch, x, baseline, {alpha, sx, sy, color}) = drawImage(sprite, x − 14, baseline − 118) at fractional positions, scaled by (sx, sy) around (x + DW/2, baseline − 36) for digits and (x + CW/2, baseline − 36) for the comma (x = the column's left edge). glyphHalf(ch, x, baseline, 'top'|'bot', sy) = only the top rows (0–82 of the sprite) or the bottom rows (82–150), scaled vertically by sy around the line baseline − 36 (the hinge). Fade window fadeWindow(fn): draw fn into an offscreen 470×222 canvas, then mask it with destination-in by a vertical gradient: transparent at y 72, opaque from y 94 to 182, transparent at y 192; then draw it on the stage — vertically moving digits never cover the segmented control or the bar. Tap indicator (drawn last) for tap k at (40 + 97.5·(((k+1) mod 4) + 0.5), 47), i.e. on the day that becomes selected; a = seconds since that tap, wrapped to −2…+2; visible for −0.42 ≤ a < 0.4; circle radius 22.575, fill rgba(215,215,230,0.38), shadow black 35% blur 10, border 3.5px white 92% (the scale applies to the whole circle incl. its stroke; the ring is not scaled); scale lerp(1.25, 1, ease((a+0.42)/0.32)) for a < −0.1, lerp(1, 0.8, (a+0.1)/0.1) for −0.1 ≤ a < 0, lerp(0.8, 1, ease(a/0.2)) after; opacity clamp((a+0.42)/0.18) before, clamp(1 − (a−0.12)/0.25) after; for 0 ≤ a < 0.4 a 3px white ring radius 22.575·(1 + 2a) at opacity 0.7(1 − a/0.4), under the circle. springF(ω₀, ζ)(t) = 0 for t ≤ 0, else 1 − e^(−ζω₀t)(cos ω_d t + (ζω₀/ω_d) sin ω_d t), ω_d = ω₀√(1−ζ²). Easing (k clamped 0–1): ease = 1 − (1−k)³; easeIn = k³; easeIO = 4k³ for k < 0.5 else 1 − (−2k+2)³/2. seg(x, a, b) = clamp((x−a)/(b−a)); bump(x, a, b) = sin(π·seg). mix = per-channel RGB blend. hash(i) = fract(sin(127.1i + 311.7)·43758.5453). A = format(VALS[from]), B = format(VALS[to]). At rest all six cards look identical (white number). Every value depends only on u, so 4.0s equals 0s.
Each digit column rolls like a car odometer, passing through every digit between the old and the new one; the right column starts first.
- The comma is drawn still (white). The four digits are drawn inside fadeWindow.
- Column ci = 0–3 (left to right), old digit a = A[i], new digit b = B[i], dir = +1 if up else −1; steps n = (b − a + 10) mod 10 if up, else (a − b + 10) mod 10.
- Delay d = 0.05·(3 − ci) (right column first, left column last at 0.15s); pos = n·ease(seg(dt, d, d + 0.6)).
- For m = floor(pos) and floor(pos)+1: off = m − pos; digit = (a + dir·m) mod 10; draw at baseline 166 + dir·off·84 (up: the next digits come from below; down: from above), opacity clamp(1 − min(1, |off|)/0.8), sy = 1 − 0.25·min(1, |off|) (a little squash like a drum).