숫자 카운트업 카드
자릿수마다 롤러가 굴러 올라가다, 일의 자리부터 차례로 서고 맨 앞자리가 마지막에 「착」 선다.
설정값 미리보기
바꾼 문구·색으로 다시 재생합니다
프롬프트 설정
Claude 가 읽는 제작 지시문입니다. 직접 읽지 않아도 됩니다.
숫자 카운트업 통계 카드 세로 영상을 HTML 파일 하나로 만들어 줘. 미리보기에서 바로 재생되게. 길게 설명할 테니 숫자는 그대로 지켜 줘.
핵심 아이디어: 화면 높이의 5분의 1이 넘는 큰 숫자의 자리마다 세로 롤러(기계식 계수기의 숫자 띠)가 하나씩 있다. 첫 프레임부터 모든 롤러가 위로 굴러 올라가며 숫자가 화면 위아래로 쏟아진다. 그러다 일의 자리부터 한 자리씩 「착」 멈추고, 높은 자리일수록 더 오래 감속해 늦게 선다 — 맨 앞자리는 혼자 천천히 기어 올라와 마지막에 선다. 멈출 때마다 띠가 정답 칸을 살짝 넘쳤다가 되돌아온다. 숫자가 다 서면 숫자 위아래 틈에 라벨이 올라오고, 잠시 뒤 다음 카드가 아래에서 화면 전체를 밀어 올린다(띠가 한 칸 넘어가듯). 카드 3장을 차례로 보여 주고 처음으로 이어진다. 정답 숫자는 띠 위의 실제 칸에 들어 있어 굴러 들어와 멈춘다 — 마지막에 바꿔 끼우는 것이 아니다.
[바꿀 곳]
- 카드 1: 위 라벨 「누적 방문자 (만 명)」 · 숫자 128 · 아래 라벨 「지난달보다 +12%」(강조 부분 「+12%」) · 배경 #111216 · 글자 #F4F1EA · 강조 #FF5A36
- 카드 2: 위 라벨 「이번 달 새 구독 (만 명)」 · 숫자 4.8 · 아래 라벨 「하루 평균 1,600명」(강조 부분 「1,600명」) · 배경 #F4F1EA · 글자 #15161A · 강조 #2F5BFF
- 카드 3: 위 라벨 「다시 찾은 비율 (%)」 · 숫자 74 · 아래 라벨 「업계 평균의 2배」(강조 부분 「2배」) · 배경 #FF5A36 · 글자 #15161A · 강조 #FFFFFF
- 숫자 문자열 규칙: 0~9 만 롤러가 된다. 소수점·쉼표는 처음부터 제자리에 고정된 틀이다. 단위(만·명·%)는 숫자 줄에 넣지 않고 위 라벨 괄호에 쓴다.
- 긴 숫자는 만·억 단위로 줄여 쓰면 더 크게 보인다. 숫자 줄은 화면 폭 93% 안에 들어가야 해서 자리가 많을수록 글자가 작아진다 — 「128」(3자리)은 숫자 잉크가 화면 높이의 약 20%(글꼴에 따라 20~22%), 「1,284,000」은 약 8%. 숫자 칸은 3자리(또는 2자리 + 소수점)까지를 권한다.
- 길이: 12초 = 카드 3장 × 4초 (끝나면 처음으로 이어서 반복)
- 화면비: 9:16 (캔버스 1080×1920)
- 글꼴: 'Pretendard', 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif · 숫자 굵기 800(없으면 그 글꼴의 가장 굵은 것) · 라벨 굵기 700, 강조 부분 800
[크기] — W = 1080, H = 1920. 카드마다 따로 계산한다.
- 숫자 줄 중심 y: cy = 0.45H.
- 자리 칸 폭 dw = 「0」~「9」 열 글자의 measureText 폭(advance) 중 가장 큰 값(자리 폭 고정, tabular). 숫자는 칸 안에서 잉크 가운데(actualBoundingBoxLeft·Right 로 잰 잉크 상자의 가로 중심)를 칸 가운데에 맞춘다 — 「1」도 칸 가운데에 선다.
- 고정 글자(소수점·쉼표)의 폭 = 그 글자의 advance. 숫자 줄 전체 폭 = 자리 수 × dw + 고정 글자 advance 합.
- 숫자 글꼴 크기 F = min(0.93W ÷ (글꼴 크기 1 일 때의 숫자 줄 전체 폭), 0.31H). 글꼴 크기 100 으로 재서 비례로 구한다. 숫자 줄은 가로 가운데 정렬. 3자리면 폭이 먼저 차서 화면 폭의 93%(advance 기준 — 잉크는 약 0.83W 라 양옆이 90px 넘게 남는다), 2자리면 높이 상한 0.31H 에 먼저 닿는다.
- 숫자 잉크 높이 inkH = measureText('0').actualBoundingBoxAscent(크기 F). 기준선 = cy + inkH/2 (숫자 잉크의 세로 중심이 cy). 고정 글자도 같은 기준선.
- 띠의 칸 간격 P = 1.36F (한 숫자에서 다음 숫자까지). 띠는 원통이 아니라 평평한 세로 띠다.
- 확인용(Pretendard 기준 — 숫자 advance 0.634em 으로 가장 넓어 숫자가 가장 작게 나온다. 괄호는 맑은 고딕): 카드 1 「128」 F ≈ 528px(577) · inkH ≈ 388px = 0.202H(422px = 0.220H) · 폭 0.93W · P ≈ 718(785) / 카드 2 「4.8」 F = 595(상한) · inkH ≈ 437px = 0.228H · 폭 0.84W(0.78W) · P ≈ 809 / 카드 3 「74」 F = 595 · inkH ≈ 437px · 폭 0.70W(0.64W) · P ≈ 809. 세 카드 모두 숫자 잉크가 0.20H 이상이다(Noto Sans KR 「128」 약 0.22H).
- 보이는 띠 높이: 숫자 줄 중심에서 칸 단위 거리 dy(= |칸 중심 y − cy| ÷ P)에 대해 창 감쇠 g(dy) = clamp((2.6 − dy) ÷ 0.8, 0, 1). dy ≤ 1.8 은 그대로, 2.6 에서 0. P 가 커서 밝은 띠(±1.8P)가 화면 위아래 밖까지 이어진다 — 돌 때는 숫자가 화면 전체를 덮는다. 멈추면 이웃 줄이 카드 1 에서 약 0.08H·0.82H(맑은 고딕 0.04H·0.86H), 카드 2·3 에서 0.03H·0.87H 에 옅게 걸친다.
- 라벨 글꼴 크기 0.032H(약 61px). 라벨은 숫자 줄과 이웃 줄 사이 틈의 한가운데에 놓는다:
위 틈 = [cy − P + inkH/2, cy − inkH/2], 아래 틈 = [cy + inkH/2 + cd, cy + P − inkH/2] (cd = 그 카드 고정 글자들의 actualBoundingBoxDescent 중 가장 큰 값, 크기 F, 없으면 0 — 쉼표 꼬리를 피한다).
라벨 잉크(그 문자열의 actualBoundingBoxAscent·Descent)의 세로 중심 = 그 틈의 가운데. 가로 가운데 정렬.
확인용(Pretendard, 카드 1): 위 틈·아래 틈 각 약 330px(맑은 고딕 363px) 에 라벨 잉크 약 60px. 위 라벨 중심 약 0.26H, 아래 라벨 중심 약 0.64H(카드 2·3 은 0.24H·0.66H). 가장 긴 라벨 「이번 달 새 구독 (만 명)」 약 545px = 0.50W(맑은 고딕 640px).
- 라벨 색: 글자 색 불투명도 78%. 아래 라벨의 강조 부분만 강조 색 100%, 굵기 800. 두 부분을 각각 measureText 해서 이어 붙인 전체를 가운데 정렬.
[롤러 — 띠 위치는 전부 닫힌 식]
- 자리 번호 k = 0 은 맨 오른쪽 숫자(일의 자리), 왼쪽으로 1, 2, … m−1 (m = 그 카드의 숫자 자리 수). 고정 글자는 번호를 받지 않는다. d_k = 그 자리의 목표 숫자.
- 띠 위 칸 n(정수, 음수도 있다)에 적힌 숫자 = ((n mod 10) + 10) mod 10. 칸 n 의 화면 y 중심 = cy + (n − s)·P. 그래서 s 가 늘면 띠가 위로 올라가고, 아래에서 다음 숫자(+1)가 올라온다 — 굴러 올라가며 세는 계수기다. 멈춘 자리에서 바로 위 칸은 d−1, 바로 아래 칸은 d+1 이다.
- 카드 시간 τ: 카드 c(0, 1, 2)의 τ = ((t − 4c + 0.5) mod 12) − 0.5. 범위 −0.5 ≤ τ < 11.5. τ ≤ 4.0 일 때만 그 카드를 그린다. τ = 0 이 그 카드가 화면을 다 덮은 순간이다.
- 자리 k 의 상수(마지막 자리 = k = m−1, 가장 높은 자리):
멈춤 시각 h_k = 0.40 + 0.15·k, 마지막 자리만 0.30 을 더한다.
감속 시간 Td_k = 0.45 + 0.07·k, 마지막 자리만 0.35 를 더한다.
최고 속도 V_k = 9 × 0.60^k (칸/초 — 계수기처럼 낮은 자리일수록 확연히 빠르다: 9 · 5.4 · 3.24. 일의 자리는 흐릿하게 흐르고 맨 앞자리는 숫자가 읽히는 빠르기로 넘어간다. 모든 열이 같은 빠르기로 돌면 슬롯머신 릴로 읽힌다).
도착 속도 v_k = max(1.5, 3.0 − 0.4·k), 마지막 자리만 1.0.
tD = h_k − Td_k (감속 시작).
- 띠 위치 s_k(τ):
1) τ < tD: s = s0 + V·τ (등속. 카드가 밀려 들어오는 동안에도 돈다)
2) tD ≤ τ < h_k, x = (τ − tD)/Td: s = s0 + V·tD + Td·( v·x + (V − v)·(1 − (1 − x)³)/3 ) — 속도가 v + (V − v)·(1 − x)² 로 처음엔 빠르게, 끝에선 천천히 줄어 h_k 에 정확히 v 로 정답 칸에 닿는다.
3) τ ≥ h_k, u = τ − h_k: s = N + (v/30)·e^(−12u)·sin(30u) — 「착」. u = 0 에서 위치도 속도(v)도 이어진다.
- 출발 위치 s0 와 정답 칸 N: S0 = V·tD + Td·(v + (V − v)/3) 를 먼저 구하고, s0 = ((d_k − S0) mod 10 + 10) mod 10, N = S0 + s0 (정수가 되고, N 칸의 숫자 = d_k).
시작할 때 콘솔에 카드마다 k · d · h · V · v · s0 · N · s(h) 표를 출력한다(s(h) 가 N 과 다르면 식이 틀린 것이다).
확인용(카드 1 「128」, k = 0~2): h = 0.40·0.55·1.00 · Td = 0.45·0.52·0.94 · V = 9.00·5.40·3.24 · v = 3.0·2.6·1.0 · s0 = 6.200·0.001·9.164 · N = 8·2·11.
확인용(카드 2 「4.8」·카드 3 「74」, k = 0~1): h = 0.40·0.85 · Td = 0.45·0.87 · V = 9.00·5.40 · v = 3.0·1.0 · s0 = 카드 2 6.200·1.962 / 카드 3 2.200·4.962 · N = 카드 2 8·4 / 카드 3 4·7.
(s0 는 글꼴과 상관없다. s0 가 0.001 처럼 0 에 붙어도 정상이다.)
- 넘침 확인용(Pretendard 카드 1, P ≈ 718): 일의 자리(v = 3)는 멈춘 뒤 u ≈ 0.040초에 정답 칸을 0.058칸(약 41px = 숫자 잉크 높이의 11%) 위로 넘쳤다가, u ≈ 0.144초에 반대로 약 12px 내려오고, 0.36초 뒤 1px 안에 든다. 십의 자리(v = 2.6)는 약 36px. 마지막 자리는 v = 1.0 이라 넘침이 약 14px 뿐이라서 아래 덜컥임이 「착」을 세운다.
- 덜컥임: 마지막 자리가 멈추는 순간부터(u = τ − h_마지막 ≥ 0) 그 카드의 숫자 줄 전체(모든 롤러·고정 글자, 옅은 이웃 줄 포함)를 아래로 0.035H·e^(−18u)·sin(45u) 만큼 옮긴다. 최대 약 39px(u ≈ 0.026초) — 일의 자리의 넘침(약 41px)과 같은 세기라, 기어 온 맨 앞자리가 서는 순간이 첫 「착」만큼 친다. u ≈ 0.096초에 약 11px 위로 되튀고, 라벨이 출발하는 u = 0.12 에는 약 6px 남는다. 라벨은 덜컥임을 받지 않는다.
- 마지막 자리는 최고 속도부터 3.24칸/초로 느리고 감속 0.94초(카드 1), 도착 속도 1.0칸/초라 마지막 0.5초 동안 약 0.6칸만 간다 — 목표 숫자가 바로 아래 이웃 줄 자리에서 천천히 올라와 선다. 다른 자리가 다 선 화면에서 혼자 기어 오르는 것이 이 작품의 긴장이다.
[밝기 — 도는 동안 띠 전체, 멈추면 숫자 줄만]
- 자리마다 초점 f_k(τ): 1(돈다) → 0(섰다). 보통 자리는 [h_k − 0.10, h_k + 0.25], 마지막 자리는 [h_k − 0.55, h_k − 0.10] 구간에서 f = 1 − easeInOutSine(진행률), 앞은 1, 뒤는 0.
- 칸 하나의 불투명도 a = g(dy) · ( f + (1 − f)·( 0.14 + 0.86·max(0, 1 − dy) ) ).
돌 때(f = 1)는 창 안의 모든 칸이 밝다. 서면(f = 0) 숫자 줄 칸만 1, 이웃 줄(dy = 1)은 0.14, 그 다음 줄은 약 0.10 — 기계식 계수기처럼 위아래 숫자가 옅게 남는다.
마지막 자리는 기어 오르는 동안 초점이 먼저 닫혀서, 올라오는 목표 숫자가 줄 자리에 가까워질수록 밝아진다(카드 1: h − 0.55 에 목표 칸이 약 0.7칸 아래, h − 0.10 에 0.10칸 아래).
[흐림 — 돌 때 세로로만, 장 간격은 이동 거리로]
- 숫자 0~9 를 카드마다 시작할 때 한 번 스프라이트(작은 캔버스, 폭 dw, 잉크 위아래 여백 포함)로 그려 둔다. 색은 상관없다(아래에서 다시 칠한다). 스프라이트와 아래 임시 캔버스는 메인 캔버스와 같은 픽셀 배율로 만든다.
- 자리마다(한 번에 한 자리씩, 임시 캔버스 하나를 돌려 쓴다. 크기 = 칸 폭 dw × 창 높이 5.2P):
① 반 프레임(1/120초) 동안 움직인 거리 dpx = |s(τ) − s(τ − 1/120)|·P. 샘플 수 K = min(16, max(1, ceil(dpx ÷ 4))) — 샘플 사이가 약 4px.
② 임시 캔버스를 비우고 globalCompositeOperation = 'lighter'. j = 0..K−1 마다 τ_j = τ − j ÷ (120·K) 의 s 로 창 안 칸들(n = floor(s − 2.6) … ceil(s + 2.6))을 globalAlpha = a ÷ K 로 스프라이트를 그린다. 샘플 시각은 카드 시간 τ 에서 빼기만 하고 감싸지 않는다(카드 시간 식이 음수에서도 이어진다).
③ globalCompositeOperation = 'source-in' 으로 임시 캔버스 전체를 글자 색으로 칠하고, 'source-over' 로 돌려놓은 뒤 메인 캔버스의 그 자리 칸에 그린다(임시 캔버스 위끝 = cy − 2.6P, 카드 위끝 y 와 덜컥임만큼 옮겨서).
같은 칸끼리는 겹치지 않고 a ÷ K 의 합이 1 을 넘지 않아서, 이렇게 하면 K 장의 정확한 평균이 된다.
- 확인용(Pretendard): 밀어 넣는 동안(최고 속도) 일의 자리 dpx ≈ 54px → K = 14(카드 1), 61px → K = 16(카드 2·3), 간격 약 3.8px. 십의 자리(5.4칸/초) dpx ≈ 32·36px → K = 9·10, 카드 1 백의 자리(3.24칸/초) dpx ≈ 19px → K = 5. τ = 0 에는 일의 자리가 이미 감속 중(약 7.7칸/초, dpx ≈ 46px → K = 12)이다. 도착 속도(3칸/초)에서 카드 1 dpx ≈ 18px → K = 5. 서면 K = 1 이라 숫자가 칼같이 선명하다. 돌 때도 숫자의 꼴이 반쯤 읽혀야 한다 — 「숫자가 굴러간다」가 보이는 것이 이 작품이다.
- 카드를 밀어 올리는 움직임에는 흐림을 넣지 않는다(화면 전체를 수십 번 겹쳐 그리게 된다). 흐림은 띠가 카드 안에서 움직인 거리로만 잰다.
[장면]
카드 하나 4초, 카드 c 는 t = 4c 에 화면을 다 덮는다. 아래 시각은 카드 시간 τ(카드 1 은 τ = t).
- τ −0.50~0.00 밀어 넣기: 새 카드가 화면 아래에서 올라오고 이전 카드는 위로 나간다. 새 카드 위끝 y = H·(1 − e), 이전 카드 위끝 y = −H·e, e = easeInOutCubic((τ + 0.50) ÷ 0.50). 두 카드는 한 경계를 공유해 틈도 겹침도 없다. 새 카드의 롤러는 이미 최고 속도로 돌고 있다(밝은 띠 전체가 흐르며 올라온다). 카드마다 화면 전체가 그 카드의 배경색 면이다.
- τ 0.00: 카드가 화면을 다 덮었다. 모든 롤러가 돌고(일의 자리는 이미 감속을 시작했다), 고정 글자(소수점)만 숫자 줄 자리에 서 있다. t = 0 첫 프레임이 이 화면이다 — 높이 0.20H 가 넘는 밝은 숫자가 위아래로 화면 전체를 흐르는 꽉 찬 화면. 오른쪽 열은 흐릿하게, 왼쪽 열은 숫자가 읽히는 빠르기로 — 자리마다 빠르기가 다른 계수기다.
- τ 0.40부터 시그니처: 일의 자리부터 0.15초 간격으로 「착·착」, 서는 자리마다 넘쳤다 되돌아오고 이웃 줄이 옅어진다. 마지막(가장 높은) 자리만 0.30초 더 늦게, 천천히 기어 올라와 선다 + 덜컥임.
카드 1: 0.40(「8」) · 0.55(「2」) · 1.00(맨 앞 「1」) / 카드 2(t = 4.40·4.85): 0.40(「8」) · 0.85(「4」) / 카드 3(t = 8.40·8.85): 0.40(「4」) · 0.85(「7」).
- h_마지막 + 0.12: 위 라벨이 올라온다. h_마지막 + 0.22: 아래 라벨이 올라온다. 각 0.40초 easeOutQuart.
잘라 내기 상자 = 그 라벨의 최종 잉크 상자를 위아래로 라벨 잉크 높이의 0.15배씩 넓힌 띠(가로는 화면 전체). 출발 위치는 최종 자리에서 라벨 잉크 높이의 1.20배 아래다 — 출발 순간 라벨은 상자 아래 가장자리 밑에 완전히 숨어 있고, 획이 상자 아래 가장자리에서 비집고 올라온다. 틈 전체(약 350px)를 상자로 쓰면 출발 자리가 틈 안이라 라벨이 첫 프레임에 그냥 보인다. 라벨 한 줄이 한 덩어리로 올라온다.
카드 1 은 1.62초에 라벨까지 다 서고, 2.0초 가까이 머문다.
- 라벨이 선 뒤 τ 3.50 까지 머묾. 아무것도 움직이지 않는다(읽는 시간).
- τ 3.50~4.00 다음 카드가 밀어 올린다(= 다음 카드의 τ −0.50~0.00). 카드 3 다음은 카드 1 이고, t = 12.00 화면 = t = 0.00 화면이다(카드 1 의 τ 식이 그대로 이어지므로 띠 위치도 속도도 끊기지 않는다).
[구현]
- HTML 파일 하나로 만든다. 외부 파일·글꼴·라이브러리·네트워크 요청을 쓰지 않는다(미리보기에서 막히거나 느려진다).
- 첫 <script> 맨 앞에 CONFIG 객체를 두고 [바꿀 곳]의 값과 이 글에 나온 숫자(시간표·크기·색·세기)를 이름 붙여 모은다. 나중에 숫자만 바꿔 다듬을 수 있게.
- 그림은 시간 t(초)만으로 계산하는 함수 render(t) 로 그린다. requestAnimationFrame 의 타임스탬프나 performance.now() 로 t 를 구한다. setTimeout·setInterval·CSS 애니메이션·transition 으로 움직이지 않는다(프레임마다 속도가 달라지고, 다시 재생할 때 어긋난다). 시뮬레이션처럼 상태가 쌓이는 작품은 고정 시간 간격으로 상태를 진행하되 그 진행도 타임스탬프로만 정한다.
- 난수는 시드 고정 난수(mulberry32 등)만 쓴다. Math.random 은 쓰지 않는다(매번 다른 화면이 나온다).
- 캔버스 내부 해상도는 화면비에 맞춘 기준 크기로 고정하고, 창 크기에 맞춰 화면비를 지키며 가운데에 꽉 차게 보이게 한다(남는 곳은 배경색). 스크롤이 생기지 않게 한다. devicePixelRatio 는 그리는 선명도에만 반영한다.
- 글자는 시스템 글꼴만 쓴다: 'Pretendard', 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif. 붓글씨·손글씨 느낌은 글꼴이 아니라 획을 그려서 낸다.
- 길이가 정해진 작품은 끝나면 처음과 같은 화면으로 돌아가 이음매 없이 반복한다.
- 모든 함수·상수·셰이더 문자열을 먼저 정의하고, 시작(초기화와 첫 requestAnimationFrame)은 스크립트 맨 끝에서 한 번만 호출한다. 정의되기 전에 쓰면 첫 화면에서 멈춘다.
이 작품에만 해당하는 구현:
- 기준 크기는 1080×1920 이다. 글에 나오는 mod 는 전부 결과가 0 이상인 나머지다(JS 의 % 는 음수를 돌려주므로 ((a % b) + b) % b).
- 띠 위치는 위 1)~3) 식 그대로의 함수 reelPos(card, k, τ) 하나로 만들고, 흐림 샘플도 같은 함수를 다른 τ 로 부른다. 카드마다 F·dw·P·inkH·cd·글자 x 위치·스프라이트·자리별 h·Td·V·v·tD·s0·N 은 시작할 때 한 번 계산해 둔다. 글꼴 폭은 그 기기의 글꼴로 measureText 해서 코드가 계산한다.
- 그리는 순서(매 프레임): 화면을 지금 카드들의 배경색으로 → 보이는 카드마다(위끝 y 만큼 옮기고 그 카드 사각형으로 잘라서) 배경 면 → 자리마다 흐림 누적한 띠(덜컥임 적용) → 고정 글자(덜컥임 적용) → 위·아래 라벨.
- CONFIG.cards 에 [바꿀 곳]의 카드 3장(위 라벨·숫자 문자열·아래 라벨과 강조 부분·배경·글자·강조 색)을 배열로 둔다.
- CONFIG.timing 에 이름 붙여 모은다: cardLen 4.0 · push 0.50 · loop 12.0 · hitStart 0.40 · hitGap 0.15 · lastExtra 0.30 · decel 0.45 / decelStep 0.07 / decelLastExtra 0.35 · vMax 9 / vMaxRatio 0.60 · vArrive 3.0 / vArriveStep 0.4 / vArriveMin 1.5 / vArriveLast 1.0 · spring ω 30 / c 12 · focus[−0.10, +0.25] / focusLast[−0.55, −0.10] · jolt 0.035H / ω 45 / c 18 · labelTop +0.12 / labelBottom +0.22 / labelDur 0.40.
- CONFIG.look 에 cy 0.45 · widthFill 0.93 · fontCap 0.31 · pitch 1.36 · windowFull 1.8 / windowEnd 2.6 · dimNeighbor 0.14 · labelSize 0.032 · labelAlpha 0.78 · blurWindow 1/120 · blurStepPx 4 · blurMax 16(느리면 1).
- 시작할 때 콘솔에 「합격 기준」 표를 카드마다 한 줄씩 출력하고 각 칸에 PASS/FAIL 을 붙인다(그 기기의 글꼴로 잰 값):
① 숫자 잉크 높이 inkH ÷ H ≥ 0.20 ② 숫자 줄 advance 폭 ÷ W ≤ 0.93 ③ 위 틈·아래 틈 ≥ 라벨 잉크 높이 × 1.3(라벨 가림 상자가 틈 안에 들어간다)
④ 가장 긴 라벨 폭 ≤ 0.90W ⑤ 모든 자리의 |s(h) − N| < 1e-6. FAIL 이 하나라도 있으면 그 사실을 콘솔에 경고로 한 번 더 적는다(화면에는 아무것도 띄우지 않는다).
[하지 말 것]
- 숫자 값을 0 에서 목표까지 세어 올린 뒤(값 = 목표 × 진행률) 반올림해 글자로 찍지 않는다 — 아래 자리가 프레임마다 다른 숫자로 갈아 끼워져 깜빡이는 소음이 되고, 띠가 굴러가는 것이 보이지 않는다. 각 자리는 자기 띠 위치 s 의 닫힌 식으로만 움직인다.
- 높은 자리(왼쪽)부터 멈추게 하지 않는다 — 앞자리가 먼저 서면 숫자의 크기가 처음에 드러나고 끝은 일의 자리 하나로 김빠진다. 숫자의 크기를 정하는 맨 앞자리가 마지막에 혼자 선다.
- 긴 숫자(1,284,000 같은 7자리)를 그대로 숫자 줄에 넣거나, 단위 「만」·「%」를 숫자 줄 끝에 붙이지 않는다 — 폭 93% 에 맞추느라 숫자 잉크가 화면 높이의 8~14% 로 줄어 세로 화면 가운데 가는 띠가 된다. 단위는 위 라벨 괄호로 간다.
- 모든 열을 같은 빠르기로 돌리지 않는다 — 같은 속도로 도는 띠들은 슬롯머신 릴로 읽힌다. 계수기는 낮은 자리가 빠르고 높은 자리가 느리다(V = 9 × 0.60^k).
- 숫자마다 다른 폭(비례폭)으로 놓지 않는다 — 폭이 좁은 「1」이 지나갈 때마다 숫자 줄 전체가 좌우로 흔들린다. 칸 폭은 가장 넓은 숫자 폭 하나다.
- 속도를 프레임마다 곱해서 줄이는 방식(v *= 0.95)으로 감속하지 않는다 — 정답 칸에 정확히 서지 않고, 멈추는 시각이 기기의 프레임률에 따라 달라진다.
- 멈춘 뒤 정답 숫자를 덮어 그리거나 크로스페이드로 바꿔 끼우지 않는다 — 「착」은 정답 칸이 실제로 굴러 들어와 넘쳤다가 돌아오는 순간이어야 하고, 바꿔 끼우면 한 프레임 튐이 보인다.
- 스프링·반동을 cos 꼴로 쓰지 않는다 — u = 0 에서 값이 정답 칸이 아니라서 멈추는 순간 숫자가 한 프레임에 튄다.
- 흐림을 ctx.filter 의 blur 나 그림자로 내지 않는다 — 사방으로 번져 세로로 구르는 느낌이 사라지고, 선 숫자까지 뿌옇게 된다.
- 흐림 장 수를 4장처럼 고정하거나 장 간격을 시간으로만 정하지 않는다 — 카드 2·3 최고 속도에서 4장이면 장 사이가 약 15px 라 같은 숫자가 여러 겹 줄무늬로 갈라진다. 장 간격은 이동 거리로 4px 이하.
- 흐림 장을 'lighter' 누적 없이 globalAlpha = 1/K 로 그냥 겹치지 않는다 — 겹친 곳이 1 − (1 − 1/K)^K ≈ 0.65 로 옅어져 도는 숫자가 바래 보이고, 마지막에 그린 장이 가장 진하게 남아 평균이 아니라 잔상이 된다.
- 띠를 원통처럼 위아래 끝에서 눌러 그리지 않는다 — 이웃 줄이 납작해지면 라벨이 들어갈 틈의 계산이 어긋나고, 납작한 색 면 카드와 어울리지 않는다. 띠 끝은 창 감쇠 g 로만 사라진다.
- 소수점·쉼표를 롤러로 굴리거나 늦게 나타나게 하지 않는다 — 그것들은 숫자의 자리를 알려 주는 틀이라 처음부터 서 있어야 도는 숫자가 「자리」로 읽힌다.
- 카드를 화면 가운데의 작은 둥근 사각형으로 만들지 않는다 — 화면 가운데 작은 그림이 되고 세로 화면 위아래가 빈다. 카드는 화면 전체를 채우는 색 면이다.
- 카드 전환을 페이드·크로스페이드·확대로 하지 않는다 — 띠가 한 칸 넘어가듯 아래에서 밀어 올려야 다음 카드가 계수기의 다음 칸으로 읽히고, 반복 이음매도 그 밀어 올림 안에 숨는다.
- 막대그래프·화살표(▲)·아이콘·이모지·진행 점·페이지 번호를 넣지 않는다 — 숫자와 라벨 두 줄이 이 카드의 전부여야 숫자가 크게 읽힌다. 화면 아래쪽은 쇼츠·릴스 화면의 글자와 버튼이 덮는 자리다.
- 파티클·반짝임·발광·컨페티·렌즈 플레어를 넣지 않는다 — 「착」의 충격은 넘침과 덜컥임이 맡는다. 빛 효과가 그것을 덮고 흔한 템플릿처럼 보이게 한다.
- 그림자·그라디언트 배경·3D 회전을 넣지 않는다 — 평평한 색 면 위의 평평한 숫자여야 흐림과 옅은 이웃 줄이 깨끗하게 읽힌다.
- 머무는 동안 숨쉬기 확대·숫자 맥박을 넣지 않는다 — 머묾의 쓸모는 숫자를 읽는 정지이고, 작은 움직임은 사건이 되지 못한 채 산만함만 더한다.
- 라벨을 타자기처럼 한 글자씩 찍지 않는다 — 숫자 쪽에 이미 「착·착·착」 박자가 있어서 라벨까지 박자를 가지면 숫자의 마지막 「착」이 묻힌다.
- 소리를 넣지 않는다 — 미리보기 자동 재생에서 막히고, 녹화에도 담기지 않는다.
- 프레임 사이에 값을 누적하지 않는다 — 반복할 때 t = 12.00 화면이 t = 0.00 화면과 같아야 하고, 누적하면 띠 위치가 어긋난다.
사용 방법
필요한 것: claude.ai 계정 — 무료 계정에서도 Claude Opus 5.5 를 고를 수 있습니다
- claude.ai 에서 새 대화를 엽니다.
- 모델 메뉴에서 Claude Opus 5.5 를 고르고, 같은 메뉴의 Effort(답변 깊이)를 High 로 둡니다.
- 복사한 프롬프트를 붙여 넣고 전송합니다. 결과로 나온 HTML 파일을 브라우저로 열면 재생됩니다.
- 권장 모델
- Claude Opus 5.5 · Effort High
- 화면비
- 9:16 (세로)
- 재생 길이
- 12초
- 결과물
- HTML 파일 하나 · 따로 설치할 것 없음
- 영상 파일
- 위 「MP4 저장 기능 포함」을 켜면 결과 화면에 녹화 단추가 생깁니다 1080 기준 · 12 Mbps · 브라우저에 따라 MP4 또는 WebM
추가 요청 예시
결과가 나온 뒤 같은 대화에서 이어서 요청하면 해당 부분만 수정됩니다.
- 카드 1 숫자를 「356」으로, 위 라벨을 「올해 누적 판매 (만 개)」로, 아래 라벨을 「작년보다 +27%」(강조 「+27%」)로 바꿔 줘.
- 세 카드 배경을 모두 짙은 남색 #14213D 로 통일하고, 숫자는 #F4F1EA, 강조는 노랑 #FFC83D 로 바꿔 줘.
- 조금 더 느긋하게 해 줘. 숫자가 돌다가 멈추는 시각은 그대로 두고, 카드마다 머무는 시간만 1초씩 늘려서 카드 하나 5초, 전체 15초로.
데이터