iso: 애니메이션 등각 설명 도구
하나의 장면은 6초에서 14초 사이의 루프에서 하나의 제품 스토리를 전달합니다. 요소들이 도착하고, 빛이 요소 사이를 이동하며, 한 번에 한 부분씩 밝아지고, 루프는 첫 프레임으로 돌아갑니다. 흐름은 하나의 형태입니다. 비트 테이블에서 스토리에 필요한 형태를 선택하세요: 레이어를 보여주기 위해 열리는 상자, 두 객체 간의 핸드오프, 채워지는 그리드, 선택지를 회전시키는 스택, 호버로 들어 올리는 타일. 모든 것은 실제 SVG 및 HTML 텍스트이며, 박스에 맞게 크기가 조정되고, 화면 밖에서는 일시 정지되며, 축소 동작 설정 시 정지 이미지로 전환됩니다.
이 키트는 이 파일 옆에 있습니다:
lib/iso.ts:Scene빌더(투영, 슬라브, 면, 와이어, 펄스, 라벨, 모션 트랙),scene.exportSvg(),responsive()및lazyBox().lib/runtime.ts: WAAPI로 렌더링된 장면을 재생하고, 장면의 40% (또는 높은 장면의 경우 화면 높이의 절반)가 보이면 인트로를 시작하고, 화면 밖에서는 일시 정지하며, 화면에서 절반 이상 멀어지면 애니메이션을 제거했다가 돌아오기 전에 같은 프레임으로 복원하고, 축소 동작 설정 시 정지하며,window.isoSeek(t)를 노출합니다.scripts/render.ts: 장면 모듈(기본 내보내기Page)을 런타임이 인라인된 하나의 독립적인 HTML 파일로 렌더링합니다.scripts/shots.mjs: 선택한 시간과 너비에서 페이지를 스크린샷으로 찍고sheet.png를 작성합니다.scripts/check.ts: 디스크 어디에든 있는 장면 파일을 키트에 대해 엄격한 타입 검사합니다 (bun scripts/check.ts scene.ts).scripts/page-idle.mjs: 여러 장면이 있는 페이지를 한 번 스크롤한 후 0%, 20%, 35%, 50%, 60%, 80%에서 멈추고 각 지점에서 메인 스레드 시간을 출력하며, CPU는 1배 및 4배로 설정합니다 (node scripts/page-idle.mjs page=<url> width=393 dpr=3 scroll=4). 장면이 여러 개 있는 페이지에서 실행하세요.scripts/perf.mjs: Chrome에서 전화기 너비로 CPU를 제한하여 페이지를 재생하고 (node scripts/perf.mjs page=<out.html> width=393 throttle=4 seconds=20) 프레임 속도, 프레임 시간 백분위수, 늦은 프레임, 긴 작업 및 메인 스레드 시간을 출력합니다. 30개 이상의 움직이는 객체가 있는 장면에서 실행하세요.scripts/contrast.mjs,scripts/render-all.ts: 렌더링된 페이지의 모든 텍스트를 정지 프레임과 추가로 네 순간에서 해당 글리프 바로 뒤의 픽셀에 대해 측정하고 4.5:1 미만이면 실패합니다 (node scripts/contrast.mjs <out.html>;bun scripts/render-all.ts <dir>는 먼저 모든 카탈로그 예제를 작성합니다). 모든 장면에서 실행한 후 완료했다고 말하세요.scripts/study-rive.mjs,scripts/compare-rive.mjs: 자신의.riv애니메이션을 프레임별로 연구하고 키트 장면과 비교하기 위한 선택적 도구입니다. 둘 다runtime=<canvas_advanced.mjs 및 rive.wasm이 있는 폴더>가 필요합니다.examples/: 가상 제품을 위한 64개의 장면, 각 파일은example(제목, 스토리, 프롬프트, 수준, 카테고리, 레이아웃, 상호작용 및art: 컴팩트 및 와이드 장면art(compact, wide, breakpoint))과 기본Page를 내보내므로scripts/render.ts가 이 중 하나를 렌더링할 수 있습니다.spot장면은 하나의 작은 장면,art(compact)입니다.hero.ts는hero(Art)를 내보내고material-gallery.ts는galleries(각 마감 패밀리당 하나의Art)를 내보내며, 각각 기본Page가 있습니다.examples/shared.ts는 표면, 색상 램프,paints, 글꼴 및fitX()를 보유하며, 이는 가장 좁은 카드 안에 라벨을 장면 내에 유지합니다.
스토리에 가장 가까운 예제를 선택하고 그리기 전에 읽으세요:
| 예제 | 수준 | 보여주는 내용 |
|---|---|---|
notifications.ts | 간단 | 최소 파일: 하나의 코어가 세 타일로 퍼져나가고, 펄스, 도착 플래시 및 홉. 먼저 읽으세요 |
ci-deploy.ts | 간단 | 체인을 따라 홉하는 패키지, 착지 시 스쿼시, 마지막에만 상태 색상 |
file-upload.ts | 간단 | 진행 표시줄을 채우는 청크, 그런 다음 가장자리 지점으로 퍼지는 복사본; 빈 슬롯의 행진 대시 |
db-branching.ts | 간단 | 실선이 되는 점선 유령, 뒤로 미끄러져 병합되는 변경 타일 |
service-map.ts | 간단 | 호버: 레이블이 호버 또는 탭 시 드러나는 9개의 slab({ hover }) 타일, 여전히 스토리를 전달하는 루프 포함 |
auth-flow.ts | 중간 | 세로 panel() 전화기, 입력된 텍스트, 토큰을 운반하는 핸드오프 유령 |
etl-pipeline.ts | 중간 | 와이어를 따라 코어로 공급되는 소스 타일, 함께 이동하도록 그 위에 있는 슬래브와 그룹화된 오버레이 |
queue-workers.ts | 중간 | 빌드가 검증하는 이벤트 테이블에 의해 구동되는 슬롯 큐 (오버플로우 없음, 빈 큐에서 가져오지 않음) |
search-index.ts | 중간 | 밝은 페이지의 선화 타일, 입력된 쿼리, 일치 강조, 오름차순으로 정렬된 결과 |
feature-flags.ts | 중간 | 재생: 라벨의 실제 <button>과 seek으로 한 루프 단계를 재생하는 인라인 스크립트 |
agent-tools.ts | 복잡 | 위성과 함께하는 코어, 호출 및 응답 펄스, 입력되는 답변 카드 |
checkout-payment.ts | 복잡 | 점선 반환 경로와 크로스페이드 상태 표시줄이 있는 단계 링 |
edge-cache.ts | 복잡 | 동일한 요청 두 번: 오리진에 대한 웜 미스, 그런 다음 엣지에서 콜 히트 |
observability.ts | 복잡 | 세 가지 신호 모양 (대시, 점, 스팬), heightTo가 있는 prism 막대, 경고 및 복구 |
keycard-slot.ts, battery-charge.ts, tile-loader.ts, empty-box.ts | 스팟 | 기능 목록, 로더 또는 빈 상태를 위한 하나의 작은 객체; 슬롯 입구에서 잘린 세로 panel() 카드, heightTo 셀, 대각선 드롭 웨이브, 행진 대시 |
sync-loop.ts, inbox-fill.ts, alert-stack.ts, table-scan.ts | 스팟 | 평면에 압착된 화살표, 유리 앞면 트레이, 맨 위 카드를 타고 가는 카운트 배지가 있는 스택 위로 미끄러지는 카드, 행별로 미끄러지는 렌즈 |
audit-ledger.ts, dns-resolve.ts, cron-jobs.ts | 간단 | 봉인과 함께 쌓이는 페이지, 한 번에 하나씩 응답과 함께 홉, 작업을 트리거하는 다이얼 |
vault-rotate.ts, firewall-filter.ts, zero-trust.ts | 중간 | 슬롯 패턴을 사용한 키 교환, 되돌아오는 거부된 패킷, 모든 요청에 스탬프 |
workload-scheduler.ts, autoscale.ts, health-check.ts | 중간 | 작은 규칙 테이블에서 배치, 새 노드를 위한 공간 만들기, 제거되었다가 다시 합류하는 노드 |
blue-green.ts, snapshot-restore.ts | 중간 | 목표가 변경된 와이어, 타임라인을 따라 뒤로 미끄러지는 커서 |
embedding-clusters.ts, training-loss.ts, recs-rerank.ts, ab-test.ts | 중간 | 클러스터로 정착하는 포인트, 떨어지는 prism 막대, 재정렬되는 슬롯 선반, 승자가 있는 분할 |
data-erasure.ts, rag-answer.ts | 복잡 | 카운터와 함께 여섯 시스템으로 퍼져나가는 하나의 요청, 모델로 날아가는 검색된 카드와 입력되는 답변 |
hero.ts | 복잡 | 하나의 프롬프트가 1, 5, 15, 40 계층으로 시스템을 성장시킴: 턴테이블 스핀인 및 가중치 드롭, 아래에서 밀려나오는 출력, 팝, 그리드 채우기로 드롭인되는 풀, 끝없는 요청, 정지 상태에서 마우스 방향으로 기울임; fill로 플래시되고 <use>로 반복되는 타일은 저렴함; SVG text()만 사용하므로 exportSvg()가 작동함 |
funnel-live.ts, billing-cycle.ts, parcel-delivery.ts, test-shards.ts | 중간, 복잡 | layout: 'wide': 3:1 스트립을 왼쪽에서 오른쪽으로 읽음 (좁아지는 단계, 점프 없이 이동하는 월 스트립, 상자를 운반하는 차량, 차선에서 경주하고 병합되는 샤드) |
kanban-move.ts, stock-sync.ts, diff-merge.ts, refund-flow.ts | 간단~복잡 | layout: 'diagonal': 하나의 등각 축을 따라 이동하는 카드 또는 토큰, 녹색으로 변하는 게이트, 두 번째 색상으로 같은 경로를 따라 역으로 실행되는 환불 |
live-cursors.ts, two-approvals.ts, design-comments.ts, translate-six.ts | 간단, 중간 | layout: 'panels': 서로 마주보는 세로 panel()들; 입력하는 커서, 자물쇠를 여는 두 개의 체크 표시, 핀과 스레드, 태국어 및 일본어 글꼴 스택의 여섯 언어로 된 하나의 메시지 |
cms-publish.ts, sensor-gateway.ts, smart-home.ts, currency-convert.ts | 간단, 중간 | layout: 'radial': 다섯 채널로 복사 하나, 읽기 후 층파 내보내기, 차례로 상태를 변경하는 장치, 링 와이어를 한 바퀴 도는 하나의 펄스 |
ota-rollout.ts, build-cache.ts, calendar-booking.ts, load-slider.ts | 간단~복잡 | layout: 'field': 중단 및 재시도와 함께 장치 필드를 가로지르는 웨이브, 종속성 테이블에서 계산된 캐시 히트, 충돌을 건너뛰는 회의; load-slider는 드래그 컨트롤 (실제 범위 입력, 마우스, 터치 및 키)로, 주변 트래픽이 계속 이동하는 동안 루프를 탐색함 |
video-transcode.ts, image-resize.ts, fraud-gauge.ts, data-lineage.ts, drill-down.ts | 간단~복잡 | layout: 'exploded': 분리되어 인코딩되는 렌디션, 벗겨지는 크기, 선을 넘어 쌓이는 위험 레이어, 레이어를 통해 아래로 조명되는 업스트림 경로; drill-down은 실제 버튼에서 해당 부분의 루프 세그먼트를 탐색하여 레이어로 열림 |
materials-*.ts, material-gallery.ts | 여섯 패밀리 (금속, 유리, 자연, 기술 패턴, 레트로, 생성)의 49가지 측면 마감재를 (scene) => Material 팩토리로, 패밀리당 라벨 없는 갤러리 하나씩. 생성 마감재는 시드를 사용함. 마감재를 직접 발명하지 말고 복사하세요 |
한 번 설정: cd <this dir>/scripts && bun install && bunx playwright install webkit (스크린샷은 설치된 Google Chrome을 Chromium으로 사용함). 타입 검사: scripts/node_modules/.bin/tsc -p <this dir>.
1. 그리기 전에 스토리보드 작성
먼저 recipes.md를 여세요. 모든 측정된 모션 및 컴포지션 패턴 (도착, 연결, 스트림, 비교, 선택, 유휴, 상호작용, 완화, 표면)이 숫자와 키트 호출과 함께 들어 있습니다. 해당 레시피에서 스토리를 구성하고 타이밍을 유지하세요.
먼저 타임라인 테이블로 스토리를 작성하세요: 뷰어가 이해해야 할 내용, 이를 보여주는 3~6개의 비트, 각 비트에 대해 어떤 요소가 어떻게, 언제, 얼마나 오래 움직이는지. 비트당 하나의 아이디어. 설명하는 데 문단이 필요한 비트는 두 개의 비트이거나 잘못된 그림입니다.
입증된 비트 모양과 측정된 타이밍:
| 비트 | 내용 | 타이밍 |
|---|---|---|
| 도착 | 조각이 하나씩 떨어지고, 약간 오버슛하고, 안착함 | dropIn: 각 0.55초, 83ms 지연, 46px 낙하 |
| 핸드오프 | 타일의 유령 윤곽선이 한 객체에서 다른 객체로 미끄러짐 | 유령 4개, 0.22초 간격, 각 1.2초, ease.io |
| 이동 | 짧은 광선 펄스가 와이어를 따라 흐름; 대상이 도착 시 깜빡임 | 270px/초, 펄스 |
| 레이어 공개 | 단색 상자가 투명해짐; 내부 레이어가 라벨과 함께 하나씩 켜짐 | 켜짐 0.23초, 유지 ~1초, 꺼짐 0.2초, 다음은 마지막이 끝날 때 시작 |
| 선택 회전 | 스택이 한 슬롯 위로 이동함; 활성 카드가 강조 색상으로 변함 | 3초마다 0.9초 이동, 느린 시작, 긴 이즈아웃 |
| 채우고 비우기 | 그리드가 타일별로 채워지고, 유지되고, 다시 비워짐 | 들어올 때 7프레임 (0.12초) 간격, 나갈 때 2프레임 간격 |
| 당기기 | 와이어가 줄어들거나 늘어날 때, 연결된 상자가 와이어를 따라 약 6px 당겨지고, 유지된 후 천천히 돌아와 와이어에 장력이 있는 것처럼 보임 | 0.23초 당김, 0.25초 유지, 0.65초 복귀 (긴 이즈아웃) |
| 호버 리프트 | 타일이 16px 올라가고 브랜드 색상을 취하며, 이름이 나타남 | slab({ hover }): 켜짐 270ms, 꺼짐 325ms, ease.out |
연결 규칙: 와이어는 양쪽 끝이 모두 화면에 있는 동안에만 표시됩니다. 루프 중간에 도착하는 것에 연결된 와이어는 펄스와 함께 그려집니다 (wire({ dash: '1 1' }), 그런 다음 at(id, 'strokeDashoffset', t, d, 1, 0, ease.linear)), 그리고 연결된 대상과 함께 사라집니다. 이러한 와이어를 인트로에 절대 배치하지 마세요. 와이어는 상자의 윗면을 절대 교차하지 않습니다: 연결하는 객체 앞에 추가하고 (객체 위에 그려지도록) 상자의 중심이 아닌 가장자리에서 시작하세요.
루프 규칙: 마지막 프레임은 첫 번째 프레임과 같습니다. 루프 중에 변경되는 모든 것은 끝나기 전에 다시 변경됩니다. 인트로 전용 모션은 intro()에 들어갑니다; 루프는 인트로가 끝날 때 시작되며, 인트로는 루프가 시작하는 것과 동일한 그림으로 끝나야 합니다. 인트로가 없는 요소는 인트로 중에 루프의 시작 값을 표시하며, 이는 루프 세그먼트의 마지막 to 값입니다.
페인트 순서는 고정되어 있습니다: 나중에 추가된 것이 항상 먼저 추가된 것을 덮습니다. 누가 누구를 덮는지 변경하는 모션 (카드가 스택 맨 위에서 맨 아래로 이동하는 것)은 대신 슬롯으로 그려집니다. 각 요소는 한 단계씩 이동하고 이웃처럼 페이드 또는 리컬러되는 슬롯이며, 모든 세그먼트는 슬롯의 휴식 값에서 다시 시작하므로 모든 슬롯이 함께 점프하지만 그림은 동일하게 보입니다. 각 슬롯에 옵션당 하나의 라벨을 제공하고 활성 슬롯 옆에 표시되는 라벨을 크로스페이드하세요.
2. 레이아웃을 선택한 다음, 먼저 전화기용으로 구성
모든 예제는 layout에서 컴포지션 이름을 지정합니다: wide (왼쪽에서 오른쪽으로 읽는 긴 스트립; 와이드 장면은 약 3:1, 예: 1200x400, 중단점 720, 쇼케이스는 전체 너비 카드로 표시), diagonal (등각 축을 따른 긴 행), panels (서로 마주보는 세로 panel()들), radial (링 위에 물건이 있는 코어), field (높은 곳에서 본 많은 타일; 약간 더 가파른 ratio가 도움이 됨), exploded (수직으로 분리된 레이어) 또는 object (기능 목록 또는 빈 상태를 위한 하나 또는 두 개의 객체). 그리기 전에 스토리에 필요한 것을 선택하세요; 다양한 장면이 있는 페이지가 더 잘 읽힙니다.
뷰어가 재생할 수 있는 장면 (interaction: 'play' | 'drag' | 'explore')은 art()의 head에 작은 인라인 모듈 스크립트를 제공합니다: label({ html })의 실제 <button> 또는 `<input type=