디오라마: 움직이는 작은 세계
정교한 내러티브 미니어처나 픽셀 단위 장면이 필요하다면 별도의 diorama-worlds 스킬을 사용하세요. 이 스킬은 의존성 없는 SVG 일러스트레이션 워크플로우를 유지합니다.
당신은 하나의 디오라마를 만듭니다: 둥근 베이스 위에 블록으로 구성된 장면을 아이소메트릭 카메라로 바라보고, 스스로 움직이며 포인터에 반응하는 몇 가지 요소가 있는, 특정 테마로 그려진 장면입니다. 기본 테마인 toy는 파스텔 블록, 하나의 따뜻한 태양, 부드러운 그림자, 모든 물체가 몇 개의 상자와 원통으로 이루어져 있으며, 질감이 없고 한눈에 읽을 수 있는 밝고 친근한 스타일입니다. 동일한 장면 파일로 soft(크림색, 더 부드러움), mono(하나의 악센트, 나머지는 잉크 색조), line(가는 선화: 흰색 채움, 잉크 테두리, 그림자 없음), print(면마다 평평한 톤과 잉크 선, 인쇄된 일러스트레이션), night(황혼, 램프 켜짐) 등으로 그릴 수 있으며, 모든 테마 필드는 재정의 가능합니다: wobble은 손으로 잉크를 그린 듯한 효과, halo는 베이스가 페이지에 드리우는 부드러운 그림자, accent는 모든 테마에서 주제의 색상입니다. examples/ 디렉토리의 18개 예제가 기준이며, 당신이 작성할 형식입니다.
당신은 한 가지, 즉 .js 파일인 figure만 작성합니다. 커널(kit/diorama.js)과 페이지(bench.html)는 고정되어 있습니다. 절대 수정하지 말고, 변경된 복사본을 붙여넣지 말며, 커널이 이미 제공하는 것(카메라, 조명, 그림자, 화면 밖에서 대기하는 루프, 포인터, 스프링, 경로, 소품)을 다시 작성하지 마세요.
아래에 언급된 모든 파일은 이 스킬의 폴더에 있습니다. figure와 페이지는 사용자의 작업 디렉토리에 작성됩니다. scripts/build.mjs, scripts/validate.mjs, scripts/look.mjs는 해당 디렉토리에서 이 폴더의 경로를 사용하여 실행합니다.
1. 크기와 컨셉
먼저 크기를 결정하세요. 예산이 정해져 있기 때문입니다:
| 크기 | 위치 | 무대 | 파트 | 줄 수 | 움직임 |
|---|---|---|---|---|---|
hero | 랜딩 페이지 상단, README, 제품 둘러보기 | 3:2, 전체 너비 | 150–400개의 원시 요소 | ≤ 420줄 | 세 개 또는 네 개의 독립적인 루프, 항상 움직이는 무언가 |
card | 문서 페이지, 블로그 게시물, 기능 섹션 | 4:3, ~500px | 60–150개 | ≤ 240줄 | 한두 개의 루프와 포인터 반응 |
mini | 작은 공간: 빈 상태, 기능 목록, 404, 설정 섹션 | 1:1, 160–240px | 15–40개 | ≤ 150줄 | 하나의 조용한 주변 움직임 |
그런 다음 references/concepts.md를 읽고 컨셉을 한 줄로 작성하세요. 테마를 끝에 포함합니다:
이름. 장소와 그 안에 있는 것. 스스로 움직이는 것. 포인터가 하는 일. (미니의 경우: 무엇이 빠졌는가.) 테마.
예제가 아닌 제품의 세계에서 장소를 선택하세요: 항구, 부엌, 옥상, 책상, 온실, 기차 플랫폼, 발사대, 길모퉁이 등은 모두 디오라마입니다. 그런 다음 취향이 아닌 figure가 위치할 곳에 따라 테마를 선택하세요: toy는 따뜻함과 색상을 원하는 제품 페이지용; soft는 에디토리얼이나 크림색 페이지용; mono는 자체 악센트 색상( accent로 전달)이 있는 제품 UI, 문서, 또는 빽빽한 텍스트 옆; line은 미니멀하거나 기술적인 페이지, 흰색 바탕에 진한 텍스트 브랜드, 또는 조용해야 하는 빈 상태용; night는 어두운 페이지용입니다. 브랜드 색상이 있다면 accent로 넣으면 모든 테마에서 주제가 다시 색칠됩니다. 두 번째 색상은 palette로 넣습니다. references/craft.md에는 각 테마가 추가하는 규칙이 있습니다.
그런 다음 코드를 작성하기 전에 파트 목록을 작성하세요: 각 그룹별로 다섯 줄, 모든 물체와 그 특징을 결정짓는 두세 가지 특징을 명명합니다. 지면(슬래브, 구역, 도로, 물), 구조물(서 있는 것: 건물, 선반, 나무), 움직이는 것(타고 다니거나, 걷거나, 회전하거나, 들어 올리는 것), 가구(가장자리를 채우는 것: 램프, 원뿔, 상자, 벤치, 울타리), 조명(빛나는 것: 창문, 램프, 등대). 모든 파트는 다른 파트 위에 놓입니다. 아무것도 떠 있지 않습니다. 히어로 목록은 30개 물체, 카드는 10개, 미니는 3개까지입니다. 목록이 장면입니다: 읽기에 빈약하면 figure도 빈약해집니다.
물어볼 사람이 있으면 두세 가지를 제안하고 기다리세요. 물어볼 사람이 없다면 가장 강력한 정지 프레임을 가진 것을 선택하고 어떤 것을 선택했는지 말하세요. 하나의 디오라마, 하나의 장소, 하나의 이야기. 설명이 필요한 장면은 아직 컨셉이 아닙니다.
2. 구축
references/craft.md를 읽으세요. 열 가지 규칙이 디오라마를 큐브 더미가 아닌 장소처럼 보이게 만듭니다. 하나라도 어기면 완성된 것이 아닙니다.kit/diorama.js상단의 인덱스(var Diorama위의 주석)를 읽으세요. 호출할 수 있는 모든 것이 나열되어 있습니다. 그 아래 코드는 읽지 마세요.- 당신의 크기와 테마에 가장 가까운 예제를 읽으세요:
examples/town.js(hero, toy: 작은 도우미 함수로 만든 전체 마을, 여러 랩, 주기적으로 켜지는 조명),examples/island.js(hero, toy: 물이 있는 장소, 정지가 있는 랩, 갈매기와 구름),examples/farm.js(hero, toy: 들판, 동물, 정지가 있는 랩) 또는examples/warehouse.js(hero, toy: 셔틀과 부두가 있는 마당) 또는examples/harbour.js(hero, toy: 18초 주기로 컨테이너를 들어 올리는 크레인이 있는 선창, 정지가 있는 트랙터 랩과 올라가는 차단기, 예인선, 등대, 리프트를 시작하는 탭, 판독);examples/cafe.js(card, soft: 사람들과 작은 것들),examples/kitchen.js(card, toy: 뒷벽과 창문이 있는 방, 호버 시 문이 열리는 껍질로 만든 냉장고, 탭하면 튀어나오는 토스터, 시계),examples/launchpad.js(card, night: 램프, 드문 이벤트, 포인터 아래에서 분해되는 로켓, 발사하는 탭, 카운트다운 판독),examples/server.js(card, mono with an accent: 리듬에 따라 켜지는 조명, 호버 시 전체 그룹이 켜짐) 또는examples/rack.js(card, mono with one accent: 포인터 반응이 있는 빈 상태) 또는examples/assembly.js(card, mono with one accent: 탭이 멈추는 게이트를 통과하는 작업 벨트, 스탬핑 암, 카운트하는 판독);examples/mailbox.js(mini, toy),examples/seedling.js(mini, line: 잉크로 그린 빈 상태),examples/observatory.js(mini, line with wobble: 회전하는 돔과 바라보는 망원경),examples/desk.js(mini, line with an accent) 또는examples/vending.js(mini, print: 움푹 들어간 부분 주위에 프레임으로 만든 기계, 노출된 코일, 팬). 이들은 모두 의도적으로 공장이 아닙니다: 디오라마는 어떤 장소든 될 수 있습니다. - 작업 디렉토리에
<name>.js형태로 figure를 작성하세요. 예제와 같은 형태로Diorama.figure({ … })호출 하나입니다:name: 소문자, 한 단어 또는 하이픈으로 연결;size:hero|card|mini.theme: 이름, 또는{ base: 'mono', accent: '#f2c230', shadows: false, … }로 필드(palette, accent, lights, shadows, finish, tone, tint, edges, outline, stroke, strokeWidth, round, glow, halo, wobble)를 재정의합니다. 한 번 구축하면 테마는 커널에 의해 모든 원시 요소에 적용되므로 figure는 테마에 따라 분기하지 않습니다.pal.accent로 중요한 것을 칠하세요: 모든 테마에서 주제의 색상이며,mono와line이 유지하는 색상이며, 브랜드 16진수가 대체하는 색상이며, 벤치의 스와치가 실시간으로 다시 색칠하는 색상입니다. 손으로 그린linefigure에는wobble: 1.4(떨림의 CSS px: 1.2는 펜, 2.5는 펠트 팁)를 추가하세요.means: 한 문장, 140자 이하, 무대 아래에 표시됩니다. 장면이 보여주는 것과 움직이는 것을 설명합니다.hint: 한 줄, 90자 이하, 포인터가 하는 일과 탭이 하는 일("로켓 위에 마우스를 올리면 단계를 볼 수 있습니다; 제어실을 탭하면 지금 발사합니다"). 페이지는 방문자가 플레이할 수 있도록 이것을 보여주며,look.mjs는 이것이 명명하는 것을 누릅니다.title: figure의 이름, 페이지가 무대 위에 표시합니다. figure 주변에 사용자 자신의 UI가 넣는 단어(제목, 줄, 버튼)는 사용자가 작성할 몫입니다. 장면은 어떤 글자도 담지 않습니다.camera:{ az, el, pad }(도 단위).az45는 아이소메트릭 기본값; 30–40은 3:2 히어로에서 넓은 베이스를 보여줍니다. 장면이 높지 않으면el을 35.264로 두세요.still: 축소된 움직임과 썸네일이 보여주는 루프의 초(second). 모든 것이 의미 있는 위치에 있는 순간을 선택하세요(트럭이 부두에, 포크가 위로).build({ D, pal }): 툴킷으로 장면을 한 번 구축하고parts를 반환합니다:tick이 움직일 모든 그룹과 메시, 그리고 포인터가 선택할 수 있는 그룹인parts.hot. 각 핫 그룹에.name을 지정하세요(boat.name = 'boat'): 페이지는 포인터가 위에 있을 때 판독으로 표시합니다.tick(ctx): 매 프레임마다D.phase,D.pulse,D.wave,D.inOut,D.path,D.spring을 사용하여ctx.t로 파트를 포즈합니다.ctx.hover로 포인터에 응답하고,ctx.pressed또는ctx.active로 누름에 응답합니다(탭은 휴대폰이 응답하는 방식이므로 히어로나 카드에는 누를 수 있는 한 가지가 있습니다: 스위치, 호출 또는 호버의 쌍둥이).D.apart는 포인터 아래에서 물체를 분해했다가 다시 조립합니다.ctx.read를 장면이 현재 무엇을 하고 있는지 설명하는 짧은 줄로 설정하세요('트럭 · 부두에 있음'): 페이지는 이것을 판독으로 표시하며, 방문자가 장면이 작동하는 모델이지 단순한 루프가 아님을 알게 하는 방법입니다.references/motion.md에 패턴이 있습니다.
- 조립:
node <skill>/scripts/build.mjs <name>.js는diorama-<name>.html을 작성합니다: 벤치, 커널, figure를 포함합니다. 커널은 SVG를 마치 일러스트레이터가 깊이를 가짜로 만드는 방식(아이소메트릭 투영, 면당 하나의 평평한 톤, 장면의 뒤에서 앞으로 칠해진 조각, 그림자는 지면에 모양으로 던져짐)으로 그리므로, 페이지는 렌더러가 필요 없고, WebGL이 필요 없으며, 네트워크 요청을 만들지 않습니다. 그림은 벡터이므로 어떤 크기에서도 선명하며, 페이지가 스타일을 지정할 수 있습니다.
3. 확인
node <skill>/scripts/look.mjs <name>.js를 실행하세요. 페이지를 빌드하고, 검증하고, 헤드리스 Chromium에서 열고,diorama-<name>-look.png를 작성합니다: 정지 프레임, 루프의 세 순간, 포인터의 응답, 카메라 기울임, 누름, 썸네일 및 전체 페이지. 콘솔, 채움, 움직임, 응답 및 누름을 숫자로 출력합니다. 모든FAIL을 수정하고,SMALL,STILL,FAINT,MUTE줄을 질문으로 읽으며, 종료 코드 0이 될 때까지 반복하세요. 누름은 힌트가 "tap", "click" 또는 "press" 뒤에 명명한 핫 그룹에 착지합니다(또는--press name, 또는--press x,y).MUTE는 힌트가 누름을 약속했지만 아무것도 변하지 않았음을 의미합니다.--theme line(또는 다른 이름)을 추가하여 동일한 figure를 다른 테마로 확인하세요.toy와line에서 모두 잘 읽히는 figure는 올바르게 구축된 것입니다. 또한clash를 출력합니다: 다른 파트를 통과하는 움직이는 파트; 나무를 통과하는 차량이나 버스를 통과하는 자동차는 수정해야 할 버그이지만, 랙 안의 포크나 경첩 위의 깃발은 괜찮습니다.references/look.md를 읽고, 그런 다음 시트를 읽고, 그 질문에 답하세요. 실패한 것을 수정한 후 1로 돌아가세요.
look.mjs는 브라우저가 필요합니다. Playwright를 찾거나 이 폴더 밖에 한 번 playwright-core를 설치합니다. 브라우저가 없으면 매 빌드 후 node <skill>/scripts/validate.mjs diorama-<name>.html을 실행하고 look.md가 "브라우저 없이"에서 설명하는 대로 look을 수행하세요. 검증기가 거부하는 페이지를 건네지 마세요. 직접 확인하지 않았다면 look이 완료되었다고 말하지 마세요.
4. 인계
사용자가 요청한 방식으로 diorama-<name>.html을 인계하세요: 파일을 원할 때 파일을 제공하고 위치를 알려주세요. 그렇지 않으면 가능한 경우 아티팩트로 게시하세요. 그런 다음 각각 한 줄씩 말하세요:
- 컨셉: 장소, 움직이는 것, 포인터와 탭이 하는 일, 테마(그리고 전환 방법: figure에서
theme:, 페이지에서?theme=와?accent=,Diorama.mount에서{ theme }; 벤치의 스와치는 대상을 실시간으로 다시 색칠합니다); - 정지 프레임: 몇 초인지, 그리고 그 순간을 선택한 이유;
- 어디에 있어야 하는지(hero, card 또는 mini) 그리고 어떻게 삽입하는지(
references/react.md는 React 또는 Next.js용; 다른 곳에서는<script>태그로 커널과 figure를 포함하고Diorama.mount(fig, { el })호출); - 확인할 수 없었던 것(노드 없음, 브라우저 없음)을 솔직하게 말하세요.
5. 조정
사용자가 변경을 요청하면 <name>.js만 편집하고, look.mjs를 다시 실행하고 새로운 시트를 읽으세요. 열 번째 버전도 첫 번째 버전과 동일한 기준으로 평가됩니다.
문제가 되는 상황
| 이런 상황을 발견하면 | 대신 이렇게 하세요 |
|---|---|
| three.js, 조명, 카메라, 캔버스 또는 WebGL에 손을 대는 경우 | 없습니다: 커널이 SVG를 그립니다. D.box, D.cyl, D.props.*, o.M(벡터용), ctx를 사용하세요. |
requestAnimationFrame, setInterval 또는 CSS 애니메이션을 작성하는 경우 | tick에서 모든 것을 ctx.t로 포즈하세요(규칙 07). |
position.x += speed * dt로 물체를 움직이는 경우 | D.path에 놓고 D.phase(t, period)로 거리를 읽으세요. 그러면 루프가 매끄럽고 정지 프레임이 재현 가능합니다(규칙 08). |
| 장면에 단어, 숫자 또는 화살표를 쓰는 경우 | 제목이나 means로 표현하세요. 장면은 어떤 글자도 담지 않습니다. 표지판조차도 없습니다(규칙 10). |
| 텍스처, 그래디언트, 글로우 또는 15번째 색상을 찾는 경우 | 팔레트 색상으로 블록 하나 더; pal.*에 필요한 것이 있습니다(규칙 03 및 04). |
figure에 if (theme === 'line')을 작성하는 경우 | 커널이 모든 원시 요소를 테마에 따라 톤, 스트로크 및 조명합니다. figure는 다섯 가지 테마 모두에서 동일합니다. |
| 브랜드 색상을 20개의 파트에 붙여넣거나 팔레트 이름으로 주제를 칠하는 경우 | pal.accent로 주제를 칠하고 브랜드 16진수를 선언에서 accent에 한 번만 넣으세요. 두 번째 색상은 palette: { cobalt: … }. |
| 호버 응답은 있지만 손가락을 위한 것은 없는 경우 | 한 가지에 누름(ctx.pressed, ctx.active)을 제공하세요: 호버는 미리보기, 탭은 실행(motion.md, "The press"). |
CAD 내보내기처럼 읽히는 line figure인 경우 | 테마에 wobble: 1.4를 추가하세요. 잉크가 손으로 그린 것처럼 휘고 오버슈트합니다. |
베이스가 "더러워 보인다"고 halo를 끄는 경우 | 할로는 디오라마를 페이지에 앉히는 것입니다. 복잡한 배경에서는 낮추고(.1), 유지하세요. |
| 판독이 제목과 같은 내용을 말하는 경우 | ctx.read는 시간을 말로 표현한 것입니다: 파트를 포즈하는 동일한 T에서 비롯된 위상, 정지, 카운트. |
| 장면 뒤에 베이스를 만들거나 아예 만들지 않는 경우 | 먼저 D.slab: 그림자가 착지할 곳이 필요합니다(규칙 01). |
| 동일한 큐브 격자처럼 읽히는 장면인 경우 | 각 물체에 그 정체성을 결정짓는 두세 가지 특징을 부여하세요(규칙 05). |
| 여덟 가지 물체가 있는 미니인 경우 | 하나의 물체, 하나의 주변 움직임(concepts.md, "A mini"). |
| 모든 것이 같은 템포로 움직이는 히어로인 경우 | 세 가지 다른 주기로 세 개의 루프(제품별, 기능별, 캐릭터별). 세 개의 루프가 히어로를 움직입니다. "같은 속도"는 세 개의 루프가 같은 주기임을 의미하지 않습니다. 세 개의 직교 리듬을 의미합니다. |
참조
references/concepts.md— 컨셉 작성 방법references/craft.md— 공예의 열 가지 규칙references/motion.md— 움직임 패턴references/look.md— 시트 확인references/react.md— React/Next.js에서의 임베딩