Motion · Biểu đồ

Bộ đếm số liệu

Con số lớn đếm lên từ 0 (animation CSS @property thuần nên seek chuẩn xác), kèm nhãn và huy hiệu delta. 4 giây, 16:9.

1920×108016:930 fps4s · 120 frameGiấy phép: CC0#number#counter#kpi#stat#data

Nguồn: gimgs ↗ · CC0

0.00s / 4sMở player ↗

Khi nào dùng

Một KPI trên màn hình: người dùng, doanh thu, lượt tải, tiết kiệm. Báo cáo, video pitch, tổng kết năm, cập nhật sản phẩm.

Cách chỉnh

  • Số lớn nên rút gọn: value: 12, suffix: "M" thay vì 12000000.
  • prefix/suffix render qua CSS content, nên giữ ngắn và đơn giản (ký hiệu tiền tệ, % đều ổn).
  • Đếm số là animation CSS trên custom property đăng ký (@property --n), vì thế mọi frame t đều cho đúng chữ số — cần Chromium ≥ 85 (Playwright/Chrome headless đều được).
  • Timeline: lưới 0–1 s, pop 0.2–0.8 s, đếm 0.3 → 0.3 + countSeconds, nhãn 1.2–1.8 s, delta 1.8–2.4 s, gạch 0.4–2.0 s.
  • Nhiều KPI: render mỗi số một clip với cùng accent/bg rồi nối.

Không đổi

window.motion, kích thước #stage, @property --n, animation-fill-mode: both.

Mọi thứ trên trang này đều có bản máy đọc. Đưa agent link JSON, hoặc thêm MCP server gimgs rồi bảo nó tìm motion template.

  1. Tải JSON — trong đó có prompt, schema tham số và toàn bộ source.
  2. Điền params (bắt đầu từ default_params) rồi mã hoá base64url vào ?p=.
  3. Với mỗi frame mở player với ?t=<giây>, chờ data-motion-ready, chụp đúng kích thước gốc, rồi ghép PNG bằng ffmpeg.
curl -s https://gimgs.net/motion/stat-counter.json
https://gimgs.net/motion/stat-counter/play?p=…&t=<seconds>
claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("stat-counter")

Prompt

Use the gimgs.net motion template "Bộ đếm số liệu".
Spec JSON (prompt + params schema + full HTML source): https://gimgs.net/motion/stat-counter.json
Raw template: https://gimgs.net/motion/stat-counter/template.html
Player for frame capture: https://gimgs.net/motion/stat-counter/play?p=<base64url JSON params>&t=<seconds>  (1920x1080, 30 fps, 4s)

1. Read the JSON and follow its "prompt" section.
2. Fill the params (start from default_params) for: <describe what you want>.
3. Render: open the player at t = i/fps for i in 0..119 in headless Chromium (viewport 1920x1080, wait for document.documentElement.dataset.motionReady === "1"), screenshot each frame, then ffmpeg -framerate 30 -i frame-%04d.png -c:v libx264 -pix_fmt yuv420p out.mp4
4. If you need to change the design, edit the HTML but keep window.motion and #stage so the same renderer works.

JSON · Markdown · llms.txt

3,873 chars · CC0Mở template gốc ↗
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Stat counter</title>
<style>
  @font-face{font-family:'Bricolage Grotesque';font-weight:600 800;font-display:block;src:url(https://gimgs.net/fonts/bricolage-600-latin.woff2) format('woff2')}
  @font-face{font-family:'IBM Plex Sans';font-weight:400 600;font-display:block;src:url(https://gimgs.net/fonts/plexsans-400-latin.woff2) format('woff2')}
  /* registered custom property → the number itself is a CSS animation, so it seeks like everything else */
  @property --n { syntax: '<integer>'; inherits: false; initial-value: 0; }
  html,body{margin:0;background:#000}
  #stage{position:relative;width:1920px;height:1080px;overflow:hidden;background:var(--bg,#0b0c10);color:#fff;font-family:'IBM Plex Sans',system-ui,sans-serif}
  .grid{position:absolute;inset:0;background-image:linear-gradient(rgba(255,255,255,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px);background-size:80px 80px;
    mask-image:radial-gradient(60% 60% at 50% 50%,#000 30%,transparent 100%);opacity:0;animation:fade 1s both}
  @keyframes fade{to{opacity:1}}
  .box{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);text-align:center}
  .num{font-family:'Bricolage Grotesque',Inter,system-ui,sans-serif;font-weight:800;font-size:300px;line-height:1;letter-spacing:-.05em;
    --n:0;counter-reset:n var(--n);animation:count var(--dur,2.2s) .3s cubic-bezier(.2,.8,.2,1) both, pop .6s .2s cubic-bezier(.2,.9,.2,1.1) both}
  .num::before{content:var(--prefix,"")}
  .num::after{content:counter(n) var(--suffix,"")}
  .num .accent{color:var(--accent,#22c55e)}
  @keyframes count{from{--n:0}to{--n:var(--target,0)}}
  @keyframes pop{from{transform:scale(.7);opacity:0}to{transform:none;opacity:1}}
  .label{margin-top:26px;font-size:44px;font-weight:500;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.6);
    opacity:0;transform:translateY(20px);animation:up .6s 1.2s cubic-bezier(.2,.8,.2,1) both}
  .delta{display:inline-block;margin-top:30px;padding:12px 30px;border-radius:999px;background:color-mix(in srgb,var(--accent,#22c55e) 18%,transparent);color:var(--accent,#22c55e);font-size:40px;font-weight:600;
    opacity:0;transform:translateY(20px);animation:up .6s 1.8s cubic-bezier(.2,.8,.2,1) both}
  .delta:empty{display:none}
  @keyframes up{to{transform:none;opacity:1}}
  .line{position:absolute;left:50%;bottom:180px;height:4px;width:0;background:var(--accent,#22c55e);transform:translateX(-50%);animation:line 1.6s .4s cubic-bezier(.2,.8,.2,1) both}
  @keyframes line{to{width:520px}}
</style>
</head>
<body>
<div id="stage">
  <div class="grid"></div>
  <div class="box"><div class="num" id="num"></div><div class="label" id="label"></div><div class="delta" id="delta"></div></div>
  <div class="line"></div>
</div>
<script>
window.motion = {
  width: 1920, height: 1080, fps: 30, duration: 4,
  params: { value: 12500, prefix: "", suffix: "+", label: "Templates rendered", delta: "▲ 38% this month", accent: "#22c55e", bg: "#0b0c10", countSeconds: 2.2 },
  apply: function (p) {
    var s = document.getElementById("stage");
    s.style.setProperty("--accent", p.accent); s.style.setProperty("--bg", p.bg);
    var num = document.getElementById("num");
    var target = Math.max(0, Math.round(+p.value || 0));
    num.style.setProperty("--target", String(target));
    num.style.setProperty("--dur", Math.max(0.3, Math.min(3.2, +p.countSeconds || 2.2)) + "s");
    // prefix/suffix go through CSS strings; quote them safely
    num.style.setProperty("--prefix", JSON.stringify(String(p.prefix || "")));
    num.style.setProperty("--suffix", JSON.stringify(String(p.suffix || "")));
    document.getElementById("label").textContent = p.label;
    document.getElementById("delta").textContent = p.delta || "";
  }
};
</script>
</body>
</html>
  1. Pick the stat
    Round it; scale with suffix (k/M).
  2. Render
    frames 0…119 at t=i/30 → ffmpeg -framerate 30 -i frame-%04d.png -c:v libx264 -pix_fmt yuv420p stat.mp4
paramtypedefaultdescription
valueinteger12500Final integer value (no thousands separators — add them via suffix/prefix text if needed)
prefixstring""Text before the number ($, €, ~)
suffixstring"+"Text after the number (+, %, k, M)
labelstring"Templates rendered"Uppercase label under the number
deltastring"▲ 38% this month"Small pill (empty string hides it)
accentstring · color"#22c55e"Pill, underline colour
bgstring · color"#0b0c10"Background
countSecondsnumber2.2How long the count-up takes

?p=eyJ2YWx1ZSI6MTI1MDAsInByZWZpeCI6IiIsInN1ZmZpeCI6IisiLCJsYWJlbCI6IlRlbXBsYXRlcyByZW5kZXJlZCIsImRlbHRhIjoi4payIDM4JSB0aGlzIG1vbnRoIiwiYWNjZW50IjoiIzIyYzU1ZSIsImJnIjoiIzBiMGMxMCIsImNvdW50U2Vjb25kcyI6Mi4yfQ