모션 피규어
이 스킬은 이동하거나 입력에 반응하는 피규어를 만듭니다. 세 가지 계층으로 구성되어 있습니다. Claude, Cursor, Codex, OpenClaw, Hermes 또는 SKILL.md를 읽는 모든 에이전트와 함께 이 스킬을 사용하세요.
| 계층 | 만드는 것 | 위치 |
|---|---|---|
| 1. 수업 피규어 | 선언적 SMIL 애니메이션 또는 SVG를 다시 그리는 슬라이더 위젯. 둘 다 `figure 펜스 안에서 마운트됩니다. | 코스 수업 |
| 2. 메커니즘 피규어 | 시스템의 명명된 부품을 보여주는 HTML 패널. 사용자가 하나의 컨트롤을 조작하고 계산된 결과를 읽습니다. | 독립형 페이지, README, 에세이, 수업 외 코스 사이트 |
| 3. 디더 필드 | 용지, 강조, 잉크 색상으로 질서 정연한 디더 점의 WebGL 밴드. 네 가지 시드 모션 포함. | 페이지 머리글 및 섹션 구분 |
계층 1에는 가장 많은 규칙이 있습니다. 수업 런타임에 하드 제한이 있기 때문입니다. 계층 2와 3에는 자체 참조 파일이 있습니다.
사용 시기
- 수업이 시간에 따라 변화하는 프로세스를 설명할 때: 단계를 거치는 토큰, 채워지는 큐, 반복되는 루프.
- 수업이 하나의 입력이 출력을 변경하는 공식을 설명할 때: 학습률, 온도, 청크 크기, 배치 크기.
- 작성자가 "이 피규어에 애니메이션 적용", "슬라이더 추가", 또는 "다이어그램을 대화형으로 만들기"라고 말할 때.
- 페이지에 사용자가 한 가지를 변경하고 시스템(캐시, 큐, 컨텍스트 창, 라우터)의 결과를 볼 수 있는 데모가 필요할 때. 계층 2를 사용하세요.
- 페이지에 코스 색상의 천천히 움직이는 헤더가 필요할 때. 계층 3을 사용하세요.
사용하지 말아야 할 때
- 아이디어가 시간 축이나 입력이 없는 고정 구조인 경우. 정적 SVG 피규어를 만드세요. 자매 스킬
blueprint-figure가 정적 피규어를 다룹니다. - 페이지가 자체 상태 모델과 머신 지오메트리를 가진 전체 설명 페이지인 경우. 자매 스킬
isometric-explainer가 이를 다룹니다. - 팔레트, 글꼴 또는 산문 규칙만 필요한 경우. 자매 스킬
course-style이 이를 보유합니다. 이 스킬은 필요한 부분을references/tokens.md로 복사합니다.
방법
-
피규어가 보여주는 단일 변경 사항을 명명하는 한 문장을 작성하세요. 두 문장이 필요하면 두 개의 피규어를 만드세요.
-
계층을 선택하세요. 수업 내에서는 계층 1을 사용하세요. 계층 2의 경우
references/mechanism-figures.md를 읽고templates/mechanism.html에서 시작하세요. 계층 3의 경우references/dither-fields.md를 읽고templates/dither.js를 복사하세요. 아래 단계는 계층 1에 대한 것입니다. 계층 1에서는 시간이 변수일 때 애니메이션 피규어를 사용하세요. 숫자가 변수일 때 슬라이더 위젯을 사용하세요. -
케밥 케이스로 이름을 선택하세요(예:
request-path또는context-budget). 먼저 레지스트리에서 해당 이름을 검색하세요. 나중에 동일한 이름을 등록하는 모듈은 이전 피규어를 대체합니다. -
코드를
figures-<주제>.js라는 모듈 파일에 넣으세요. IIFE로 감싸고window.LF를 읽은 후 없으면 조기에 반환하세요. -
function (host, cfg)피규어 함수를 작성하세요.host에 하나의.lf카드를 추가하고 dispose 함수를 반환할 수 있습니다. -
카드를 빌드하세요: 대문자
.lf-label과 짧은 힌트가 있는.lf-head,.lf-body, 캡션이 있는.lf-cap. -
SVG에
viewBox="0 0 520 H"를 사용하세요. 대부분의 코스 피규어는 200에서 250 사이의 H를 사용합니다. 단일 막대는 더 적게 필요합니다. -
렌더 함수 외부에서 한 번 생성하는 id를 가진
<title>과<desc>를 추가하세요. -
애니메이션 피규어의 경우, 먼저 항목을 추가한 다음 하나의 느린 루프를 추가하세요.
references/smil-rules.md를 한 줄씩 따르세요. -
슬라이더 위젯의 경우,
LF.slider또는LF.select를 호출하기 전에state._render를 정의하세요. 그런 다음 마지막에state._render()를 한 번 호출하세요. -
모듈 끝에서
LF.register({ 'your-name': fn })을 호출하세요. -
수업 Markdown에서 펜스를 추가하세요. 첫 번째 줄에 이름을 넣고 선택적 JSON 구성을 그 뒤에 넣으세요:
```figure context-budget {"windowK": 32} ``` -
"완료 전 확인"의 검사를 실행하세요. 밝은 테마, 어두운 테마, 375px 너비, 그리고 축소된 모션 켜짐 상태에서 피규어를 보세요.
페이지가 피규어를 마운트하는 방법
- Markdown 파서는 펜스를
<div class="lesson-figure" data-figure="name {json}">로 변환합니다. - 사이트 빌드는 수업 Markdown에서 펜스 이름을 스캔합니다. 인용된 이름을 포함하는 모듈 파일을 찾고 매니페스트를 작성합니다. 제공자가 없는 펜스 이름은 빌드를 중단시킵니다.
- 페이지는 수업에 필요한 모듈만 고정된 순서로 로드합니다. 새 모듈 파일은 나열된 파일 뒤에 알파벳 순서로 들어갑니다.
- 마운트 함수는 첫 번째 단어를 이름으로 읽고 나머지를 JSON으로 구문 분석합니다. 잘못된 JSON은 빈
cfg를 제공합니다. - 피규어 함수가 오류를 발생시키면 런타임은 호스트를 비우고 경고를 기록합니다. 수업의 나머지 부분은 계속 렌더링됩니다.
- 마운트 후 런타임은 제목, 설명,
role="img", 그리고 누락된 경우 컨트롤 레이블을 추가합니다. 피규어에 SMIL 애니메이션이 있는 경우 일시 정지 버튼을, 애니메이션이 한 번 재생되는 경우 재생 버튼을 추가합니다. - 런타임은 피규어가 뷰포트를 벗어나거나, 탭이 숨겨지거나, 사용자가 일시 정지를 누르면 애니메이션을 일시 중지합니다. 축소된 모션 또는 인쇄 모드에서는 정적 프레임을 표시합니다.
references/toolkit.md는 모든 런타임 함수를 설명하고 두 개의 완전한 예제 모듈을 포함합니다.
규칙
애니메이션 피규어:
<animate>,<animateTransform>,<animateMotion>만 사용하세요. 피규어에서setInterval또는requestAnimationFrame을 사용하지 마세요.- 각 피규어를 55개 이하의 SVG 요소로 유지하세요.
- 항목은 opacity 0과 scale 0.95에서 opacity 1과 scale 1로 시작하세요. scale을 0에서 시작하지 마세요.
- 항목은
calcMode="spline"과keySplines="0.23 1 0.32 1"을 사용하세요. 항목 지속 시간은 0.5~0.6초입니다. - 항목 시작을 0.05~0.4초 간격으로 지연시키세요. 종료는 항목보다 짧습니다.
- 루프는 2.5~6초 동안 지속되며
repeatCount="indefinite"를 사용하세요. 루프에fill="freeze"를 설정하지 마세요. 런타임이 한 번만 재생하기 때문입니다. - 각
keyTimes목록은values만큼의 항목을 가집니다. 0에서 시작하여 1에서 끝나며 절대 감소하지 않습니다. - 각
keySplines목록은keyTimes보다 하나 적은 항목을 가집니다.calcMode="spline"에서만 사용하세요. keyPoints와 함께animateMotion을 사용하는 경우calcMode="linear"를 사용하세요. keyPoints 수는 keyTimes 수와 같습니다.values는 없습니다.- 애니메이션
fill또는stroke값에var()를 넣지 마세요. 대상 색상을 가진 두 번째 요소의 opacity를 애니메이션하세요. - 루프는 opacity, transform,
stroke-dashoffset또는 경로를 따른 모션만 애니메이션합니다. 런타임은 x, y, x1, y1, x2, y2, width, height, r, cx, cy, rx, ry의 애니메이션을 한 번만 재생합니다. - 호스트의
data-static-time(기본값 1.5초)에서의 프레임은 완전하고 읽을 수 있어야 합니다. 나중 순간이 전체 상태를 보여줄 때 호스트에 속성을 설정하세요. - 요소를 중심을 기준으로 크기 조정하세요. 그룹의 내용을 (0, 0) 주위에 그리고
translate로 그룹을 이동하세요.additive="sum"으로 크기 조정을 추가하세요.
슬라이더 위젯:
- ES5만 작성하세요:
var, 함수 표현식, 문자열 연결. 화살표 함수,let,const또는 템플릿 리터럴을 사용하지 마세요. - 첫 번째
LF.slider또는LF.select호출 전에state._render를 정의하세요. 슬라이더는 생성 시 렌더 함수를 래핑합니다. state._render에서 모든 SVG 자식을 제거하고 다시 추가하세요. 노드를 제자리에서 편집하지 마세요.state._render외부에서 id를 한 번 생성하세요. 런타임은 새 노드가 가지고 있지 않은 속성(id 포함)을 제거합니다.- 막대를 길이 또는 경로의
stroke-dasharray로 늘리세요. 조정된 노드가 중심에서 크기 조정되므로 막대를 크기 조정으로 늘리지 마세요. - 각 슬라이더 레이블을 짧고 소문자로 유지하고 단위를 대괄호 안에 넣으세요(예:
chunk size (tokens)).
두 종류 모두:
- 모든 색상을 밝은 테마 값을 기본값으로 하는 CSS 변수에서 가져오세요(예:
var(--blueprint,#3553ff)). 변수가 작동하지 않을 때만 리터럴 16진수를 사용하세요. - 주요 주제에 대해 최대 하나의 강조 색상(
--blueprint)을 사용하고 두 번째 상태에 대해--warn을 사용하세요. 나머지는 잉크 및 규칙 토큰을 사용하세요. - SVG 텍스트를 12단위 이상으로 설정하고
var(--font-mono)를 사용하세요. 레이블이 더 작아야 하는 경우 SVG에 최소 너비 500px를 주고 옆으로 스크롤되도록 하세요. - 휴대폰에서 레이블 크기를 측정하세요. 375px 화면에서 카드 내부의 520단위 SVG는 279px 너비로 그려졌습니다. 12단위 레이블은 약 6.4px로 그려졌습니다.
- 캡션을 평이한 기술 영어로 작성하세요. 각 색상이 의미하는 바를 명명하세요. 문장을 25단어 이하로 유지하세요.
.lf-label의 레이블을 대문자로, 2~4단어로 제공하세요.
메커니즘 피규어 (계층 2):
- 실제 이름과 실제 숫자를 표시하세요: 파일 이름, 키, 토큰 수. 절대
item 1이나 이름이 없는 회색 막대를 사용하지 마세요. - 사용자에게 하나의 컨트롤을 제공하세요: 단계, 슬라이더, 토글, 재생 또는 부품 정지.
- 본문의 숫자에서 계산된 텍스트의 결과 줄로 끝내세요. 고정된 결과를 작성하지 마세요.
- 피규어의 35%가 보일 때 한 번 실행하고 재생 버튼을 추가하며 절대 반복하지 마세요.
cubic-bezier(0.23, 1, 0.32, 1)로transform과opacity만 애니메이션하세요. 누르기 120160ms, 드러내기 200300ms, 접기 380~500ms.- 처음 8개 항목에 대해서만 항목당 30~70ms 간격으로 목록을 지연시키세요.
- 모든 프레임에서 모든 레이블을 온전하게 유지하세요: 줄임표 없음, 겹침 없음, 점 위에 텍스트 없음. 텍스트 11px 이상, 결과 12.5px 이상.
- 320px에서 패널을 한 열로 쌓고 각 컨트롤에 40px 터치 대상을 제공하세요.
- 사이트의 다른 페이지에서 사용하지 않는 메커니즘을 사용하고 사이트의 메커니즘 테이블에 추가하세요.
디더 필드 (계층 3):
--bg,--blueprint,--ink에서 색상을 읽고data-theme이 변경될 때 다시 그리세요.- 초당 최대 30프레임으로, 밴드가 보이는 동안에만 그리세요.
- 축소된 모션에서는 하나의 정적 프레임을 그리세요. WebGL이 없으면 정적 해치를 표시하세요.
- 밴드를
aria-hidden="true"로 표시하고 레이블 칩을 제외한 점 위에 텍스트를 넣지 마세요.
완료 전 확인
- 펜스 이름이 등록된 이름과 정확히 일치하며, 다른 모듈이 이를 등록하지 않습니다.
- 모듈에
=>,let,const또는 백틱 문자열이 없습니다. - 모듈에
setInterval및requestAnimationFrame이 없습니다. -
references/smil-rules.md의 검증기가 마운트된 호스트에 대해 빈 목록을 반환합니다. - 각 애니메이션 피규어는 55개 이하의 SVG 요소를 가집니다.
- 모든 루프는 2.5~6초의 지속 시간을 가집니다.
- 어떤 루프도 규칙 11의 지오메트리 속성을 애니메이션하지 않습니다.
- 축소된 모션이 켜져 있을 때 피규어는 완전한 그림을 보여주고 누락된 요소가 없습니다.
- 어두운 테마에서 모든 선과 레이블이 보입니다.
- 375px 너비에서 모든 레이블을 읽을 수 있고 피규어 외부에 페이지가 옆으로 스크롤되지 않습니다.
- 위젯의 경우 각 슬라이더를 최소 및 최대로 이동해도
NaN, 음수 너비 또는 콘솔 오류가 발생하지 않습니다. - SVG에는 하나의 제목과 하나의 설명이 있으며, 슬라이더가 이동한 후에도 해당 id가 동일하게 유지됩니다.
- 캡션은 피규어가 사용하는 모든 색상을 명명합니다.
- 계층 2:
references/mechanism-figures.md끝에 있는 체크리스트의 모든 항목이 통과합니다. - 계층 3:
references/dither-fields.md끝에 있는 체크리스트의 모든 항목이 통과합니다.
파일
references/smil-rules.md: 12가지 SMIL 규칙 전체, 각 규칙이 방지하는 내용, 브라우저 콘솔에서 실행할 수 있는 검증기.references/toolkit.md:LF함수 및 마운트 시퀀스. 또한 완전한 슬라이더 위젯, 완전한 SMIL 피규어 및 코스 사이트 외부에서 사용하기 위한 미리보기 페이지를 포함합니다.references/tokens.md: 밝은 테마 및 어두운 테마용 색상 토큰, 글꼴, 모션 타이밍 값.references/mechanism-figures.md: 계층 2. 실제 이름, 거부된 피규어, 메커니즘 모양, 해부학, 결과, 모션 예산 및 검사.references/dither-fields.md: 계층 3. 셰이더 그리는 방법, 네 가지 모션, 마크업, 규칙, 디더 막대 및 검사.templates/mechanism.html: 완전한 계층 2 피규어, 크기 컨트롤이 있는 LRU 캐시, 모든 브라우저에서 열림.templates/dither.js: 완전한 계층 3 스크립트. 로드하고<div class="dither" data-seed="...">를 추가하세요.
AI Engineering from Scratch 저장소 내에서 런타임에 대한 site/lesson-figures.js와 더 많은 피규어에 대한 site/figures-*.js도 참조하세요.