모션 디자인 (HyperFrames 에디션)
HyperFrames 문서는 API를 가르쳐 주지만, 이 파일은 감각을 다룹니다. 아래 숫자는 실제 출시된 작품에서 비롯된 것입니다. 기본값으로 간주하세요. 편차를 주는 것은 가능하지만, 그것은 의도적이어야 하며, 단순히 신경 쓰지 않아서가 아니어야 합니다.
whaleyxbt/claude-motion의
motion-design스킬을 개작했습니다 (MIT 라이선스, 동일 폴더의LICENSE참조). 원본은 Remotion용이었습니다. 이 버전은 HyperFrames(HTML + GSAP)용으로 재작성되었으며, 중국어 번체 조판 규칙이 추가되었습니다. "(본 버전 신규)"라고 표시된 단락은 원본 내용이 아닙니다.
공식 HyperFrames 스킬과의 역할 분담 (본 버전 신규)
이 머신에는 HeyGen 공식 HyperFrames 스킬(hyperframes, hyperframes-core, hyperframes-animation 등)도 설치되어 있습니다. 역할 분담은 다음과 같습니다.
- 공식 스킬은 "구현 방법"을 담당: 프로젝트 구조,
data-*속성, API 작성법, 플로우 라우팅, registry 기성 컴포넌트. API 작성법이 이 파일과 충돌할 경우 공식 스킬을 우선합니다. - 이 파일은 "감각"을 담당: 이징, 리듬, 체류 시간, 서체, 색상, 중국어 조판. 공식
hyperframes-animation의 rules/blueprints를 사용할 때도 시간과 이징 숫자는 이 파일을 기본값으로 합니다. - 검사: 항상
review-loop를 따릅니다. 여기에는 이미 공식hyperframes check가 포함되어 있습니다.
0. HyperFrames의 하드 규칙 (본 버전 신규)
이 규칙을 위반하면 출력 시 화면이 깜박이거나, 어긋나거나, 실행할 때마다 결과가 달라집니다.
-
시간은 HTML이 결정: 각 씬은
class="clip"요소이며,data-start,data-duration으로 타임라인을 설정합니다. 루트 요소에는data-composition-id와 명확한data-duration이 있어야 합니다. -
동작은 GSAP이 담당:
gsap.timeline({ paused: true })를 사용하고,window.__timelines["<composition-id>"]에 등록하며, 키 이름은data-composition-id와 같아야 합니다. -
중요한 모든 트윈에는 명확한 위치(세 번째 인자)를 지정하고, 양쪽 끝이 모두 중요할 때는
fromTo()를 사용합니다. 출력 시 seek으로 건너뛰기 때문입니다. -
transform과opacity만 변경하고,top/left/width/height를 반복적으로 변경하지 마십시오. -
금지: CSS
transition/@keyframes,Date.now(),requestAnimationFrame,setTimeout, 시드 없는Math.random(), 출력 중에만 fetch하는 리소스. -
스크립트로 오디오/비디오를 재생, 일시 중지, seek하지 마십시오. 또한 스크립트로 시간에 따라 clip을 표시하거나 숨기지 마십시오. 이 모든 것은 data 속성에 맡깁니다. 동영상을 이동해야 한다면 외부 래퍼 요소를 움직이십시오.
-
무작위성은 항상 시드 함수를 사용합니다:
function rand(seed) { let t = (seed += 0x6D2B79F5); t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }
1. 시간은 한 곳에 집중
-
모든 비트는 이름이 있는 시점(초)이며, 씬별로 그룹화(
s1,s2…)되어 프로젝트 루트의timeline.js에 작성됩니다:window.TL = { s1: { start: 0, title: 0.3, items: [1.2, 1.45, 1.7], exit: 3.6 }, s2: { start: 3.4, drawOn: 3.5, hook: 5.2, end: 8 }, };index.html에서 모든 composition 스크립트보다 먼저<script src="timeline.js"></script>를 로드합니다. -
GSAP의 위치 인자는 항상
TL에서 가져옵니다(TL.s1.title,TL.s1.exit + 0.05와 같은 상대 표기법은 허용됨). 씬 내에서 초를 하드코딩하지 마십시오. -
씬 외곽선의
data-start/data-duration은 반드시TL의 씬 경계와 일치해야 합니다. 재타이밍 시에는 먼저timeline.js를 수정한 다음 이 두 속성을 동기화하여 수정하십시오. -
음향 효과와 내레이션은
data-start="…"속성을 가진<audio>를 사용하여 동일한 비트에 배치합니다.review-loop의 스크린샷 시간도TL에서 가져오므로, 화면, 사운드, 검사가 함께 움직입니다. -
모든 화면은 오직 시간에 의해서만 결정됩니다. 섹션 0을 참조하십시오.
2. 이징
원본의 네 가지 곡선을 GSAP에서 CustomEase로 정밀하게 재구성합니다. gsap@3/dist/CustomEase.min.js를 로드하고 gsap.registerPlugin(CustomEase)로 등록하십시오:
CustomEase.create("enter", "0.16,1,0.3,1"); // easeOut
CustomEase.create("exit", "0.6,0,0.9,0.35"); // easeIn
CustomEase.create("move", "0.65,0,0.35,1"); // easeInOut
CustomEase.create("land", "0.55,0,0.2,1.12"); // overshoot
| 곡선 | 용도 | 가장 가까운 내장 이름 |
|---|---|---|
enter = bezier(0.16, 1, 0.3, 1) | 진입, 공개, 모든 "도착" | expo.out (거의 동일) |
exit = bezier(0.6, 0, 0.9, 0.35) | 퇴장: 빠르게, 질질 끌지 않음 | 약 power3.in |
move = bezier(0.65, 0, 0.35, 1) | 두 상태 간 이동 (뒤집기, 도킹, 변형) | power2.inOut (완전히 동일) |
land = bezier(0.55, 0, 0.2, 1.12) | "안착"하는 값 (슬라이더가 특정 위치에 도달) | 좋은 내장 대안 없음, CustomEase 사용 |
ease: "none" (선형)은 연속 운동에만 사용: 회전, 표류, 입자, 초침.
한 애니메이션이 다른 값을 따라가야 한다면(예: 자막이 슬라이더 위치를 따라감) 동일한 트윈으로 프록시 객체를 구동하고 onUpdate에서 파생시키십시오. 별도의 독립 시계를 주지 마십시오.
3. 탄성
원본은 Remotion의 물리 스프링을 사용했지만, GSAP에는 스프링 물리가 없습니다. 아래 표는 이 버전에서 선택한 근사치입니다(본 버전 신규, 원본 숫자 아님). 출력 후 review-loop로 느낌을 확인하십시오:
| 느낌 | GSAP 설정 | 용도 |
|---|---|---|
| 기본 안착 | back.out(1.2), 0.6 s | 일반 UI 진입 |
| 무겁고 안정적 | power3.out, 0.8–1.0 s | 큰 패널, 반전 |
| 노브 걸림 | back.out(1.7), 0.35 s | 컨트롤이 특정 위치로 점프 |
| 튀어나옴 | back.out(2.2), 0.45 s | 레이블, 배지, 성공 점 |
| 탄성 강세 | elastic.out(1, 0.4), 0.9 s | 영화당 한 번만 사용하는 클라이맥스 순간 |
물리적 느낌이 있는 것(UI, 사물)에는 탄성을 사용하고, 텍스트와 카메라 느낌의 이동에는 베지어 곡선을 사용합니다.
4. 리듬
- 시차(stagger): 영어 단어 약 0.09 s; 중국어 글자당 약 0.04–0.05 s, 단어당 약 0.09 s (중국어 부분은 본 버전 신규); 목록 항목 및 레이블 약 0.2–0.25 s; 링 및 점 약 0.06 s.
- 텍스트 공개 약 0.8 s, 마스크 사용: 외부
overflow: hidden, 내부yPercent: 100 → 0에 약간의 회전 추가(rotation: 3 → 0). - 퇴장은 진입의 약 절반(0.35–0.55 s 대 0.7–1.25 s), 퇴장에는
exit곡선 사용. - 씬은 겹쳐야 함: 다음 씬이 이전 씬이 완전히 사라지기 전에 그리기 시작합니다(예:
s2.drawOn4.02 s가s1.flipEnd4.4 s보다 빠름). 빈 공간을 강제로 자르면 "로딩 중"처럼 보입니다. - 타이핑 문자당 약 0.035 s, 유휴 시 커서는 약 2.4 Hz로 깜빡입니다(
steps또는set을 타임라인에 배치, 타이머 사용 금지). - 읽기 체류 시간: 읽게 할 각 상태는 안착 후 멈춰야 합니다. 짧은 문장 최소 1 s, 세 단어 초과 시 단어당 약 0.25 s 추가; 중국어의 경우 약 4자당 0.25 s 추가 (본 버전 신규). 마지막 종료 문장은 최소 2 s. 원본의 22초 버전이 존재했던 이유는 15초 버전에서 글이 너무 빨리 지나갔기 때문입니다. 확실하지 않으면 더 오래 멈추고, 더 적게 움직이십시오.
5. 서체
- 최대 세 가지 글꼴 패밀리: 디스플레이용 세리프, 인터페이스 산세리프, 고정폭(레이블, 프롬프트, 숫자용).
- 영어 (원본): Instrument Serif / Inter / JetBrains Mono.
- 중국어 번체 (본 버전 신규): Noto Serif TC / Noto Sans TC, 숫자 및 레이블은 JetBrains Mono와 함께 사용. 글꼴 파일은 프로젝트의
assets/fonts/에 저장하고@font-face로 로드하며, 시스템 글꼴에 의존하지 마십시오(컴퓨터가 바뀌면 달라짐).
- 영어 디스플레이 텍스트는 크게(1080폭 캔버스에서 약 138 px), 자간 좁게(
-0.02em),line-height: 1. - 중국어 디스플레이 텍스트 (본 버전 신규): 1080폭에서 약 96–120 px, 한 줄에 약 12자 이하, 자간
0~0.02em(중국어는 음수 자간 금지),line-height: 1.15–1.25. - 한 줄에 하나의 강조점: 영어는 이탤릭체 하나에 강조 색상 사용; 중국어는 진짜 이탤릭체가 없으므로 강조 색상과 굵기/무게로 강조점을 담당합니다 (본 버전 신규).
- 고정폭 레이블: 대문자,
letter-spacing: 0.2–0.24em, 색상 흐리게. 이것들은 단지 장식입니다. 시청자가 반드시 읽어야 하는 내용은 크게 만드십시오. - 모바일 테스트: 360 px 폭(소셜 피드에서 실제로 보이는 크기)에서도 핵심 메시지를 읽을 수 있어야 합니다. contact sheet로 확인하십시오.
6. 색상 구성
- (본 버전 신규) 전체 영화는 세 가지 색상으로 톤을 정의, 프레젠테이션 템플릿처럼 사용자가 결정: 배경색
bg, 주색fg(텍스트 및 선), 강조색accent. 프로젝트의theme.json에 작성하고,motion-explainer(또는 이미지 강화 버전motion-explainer-images) 스킬의theme.py로 적용합니다. 강조색은 "답, 결론, 핵심 숫자, 챕터 카드"에만 사용합니다. - 색상 견본은
:root의 CSS 변수(--bg,--ink,--muted,--accent…)로 정의하고, 씬 안에서 새로운 색상 코드가 등장하지 않도록 합니다. - 강조색은 단 하나여야 하며, 그것은 의미가 있습니다: 변경된 것, 답, 승자. 모든 것이 강조색이면 강조가 없습니다.
- 광선(glow)은 시간이 아닌 상태에 의해 구동되어야 합니다 (
glow = effort). 빛은 이야기를 말할 수 있어야 합니다.
7. 질감: 정지한 것은 없다
- 필름 그레인: SVG
feTurbulence필터를 한 겹 겹치고, opacity 약 0.09, 두 프레임마다seed교체 (타임라인에서set으로 예약, 시드는 프레임 번호에서 계산). - 비네팅 + 점형 그리드, 초당 몇 px씩 표류:
radial-gradient비네팅, 그리드는 영화 전체에 걸친 선형 트윈 하나 사용. - 손그림 "선 떨림" (
feTurbulence+feDisplacementMap, 동일하게 두 프레임마다 시드 교체): 스케치 느낌, 낮은 완성도 상태에 사용. 품질이 향상되면 페이드 아웃. - 유휴 요소는 숨 쉬어야 함: 움직이는 시계, 깜빡이는 커서, 느린 회전.
8. 연속성과 전환
- 오브젝트를 이어가도록 하고, 강제로 자르지 마십시오. 원본의 프롬프트 바, 스파크, 슬라이더는 씬을 넘나들며 역할을 바꿉니다. 이것이 "디자인된" 것과 "짜깁기한" 것의 차이입니다. HyperFrames에서 씬을 넘나드는 오브젝트는 특정 씬 내부가 아닌 루트 composition에 배치하십시오.
- 모든 전환은 화면상의 오브젝트에 의해 생성되어야 합니다 (다섯 개의 결과 점이 하나로 합쳐져서 조리개로 변함). 공식적인 와이프 전환을 사용하지 마십시오.
- 속도 활용: 잔상, 압축은 "이 프레임과 이전 프레임의 값 차이"에서 유도하고, 인위적으로 만들지 마십시오.
- 영화당 하나의 클라이맥스 순간 (조리개 + 충격). 그것을 향해 점진적으로 구축하고, 너무 일찍 사용하지 마십시오.
9. 안티 패턴
- 모든 것을 동시에 페이드 인하거나, 모든 것에 동일한 지속 시간을 사용.
- 시작과 정지가 있는 것에 선형 이징 사용.
- 읽어야 할 텍스트가 움직이는 중.
- 한 프레임에 두 개 이상의 초점.
- 내용이 화면 가장자리에서 약 60 px 미만 (안전 영역), 의도적인 크롭이 아닌 경우.
- 0번째 프레임이 비어 있거나 완전히 검은색: 소셜 플랫폼에서 음소거 자동 재생 시 첫 프레임이 썸네일입니다.
- (본 버전 신규) 스크립트에서 오디오/비디오 재생 또는 clip 표시 제어, CSS 애니메이션 사용, 시드 없는 무작위성 사용. 섹션 0 참조.
워크플로우
- 먼저 비트를
timeline.js에 작성(숫자로 된 스토리보드). 사용자에게 리듬을 확인한 후 작업 시작. - kinocut의
hyperframes_init으로 프로젝트 생성; 각 씬은compositions/디렉토리의 composition이며, 공유 컴포넌트와 씬 간 오브젝트는index.html에 배치. - 의미 있는 수정 후에는 항상
review-loop스킬 실행. - 화면 시간이 확정된 후에 사운드 작업: 음향 효과와 배경 음악은
<audio data-start>를 사용하여TL의 비트에 맞춤. 중국어 내레이션의 억양과 감정은 사용자가 귀로 판단하도록 하고, ASR이나 유사도 점수로 대체하지 마십시오 (본 버전 신규).