Communitygithub.com

Diorama: 微缩动画世界

为网页构建小型动画3D世界(等距相机、圆角底座上的积木、柔和阴影、移动的小车辆和小人),提供六种可调主题。

Diorama: 微缩动画世界 是什么?

Diorama 是一个无需依赖的 SVG 插图工作流,用于生成自包含的 HTML 文件,其中包含一个等距微缩场景。该场景由圆角底座上的积木构成,具有柔和的阴影和自动移动的物体,适用于英雄区、卡片或小部件(如空状态、列表特性或404页面)。它支持六种主题:`toy`(柔和积木、温暖阳光)、`soft`(奶油色调)、`mono`(单一强调色、其余为墨色)、`line`(细线绘制、白色填充和墨色边缘,可手动调整)、`print`(平涂色调和墨线,类似印刷插图)和 `night`(黄昏、亮灯)。所有主题字段均可覆盖(例如 `wobble` 实现手绘墨迹效果、`halo` 控制底座阴影)。开发者只需编写一个 `.js` 文件(即 `figure`),调用 `Diorama.figure({...})` 构建场景,并使用 `scripts/build.mjs`、`scripts/validate.mjs` 和 `scripts/look.mjs` 进行构建、验证和预览。内核 (`kit/diorama.js`) 和页面 (`bench.html`) 是固定的,无需修改。Diorama 适用于 Claude Code、Cursor 或 Codex 等 AI 代理工具,每次只构建一个场景,通过 `Diorama.figure` 的 API 定义相机、主题、构建函数和逐帧动画逻辑。该技能强调精简和一致性:一个场景文件在五种主题下都能正常工作,不会分支到特定主题的代码。

兼容平台✓Claude Code~Codex CLI~Cursor✓OpenCode
npx skills add https://github.com/educlopez/diorama/tree/HEAD/skills/diorama

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Diorama:一个会动的小世界

如需详细的叙事微缩场景或像素级完成的场景,请使用单独的 diorama-worlds 技能。此技能保留为无依赖的 SVG 插图工作流。

你正在制作一个 diorama:一个由圆角底座上的积木构成的场景,从等距相机角度观看,包含一些自动移动并能响应指针的元素,以某种主题绘制。默认主题 toy 包含柔和积木、一轮温暖太阳、柔和阴影,每个物体由少量方块和圆柱组成,无纹理,令人愉悦且一目了然。同一场景文件在 soft(奶油色,更柔和)、mono(单一强调色,其余为墨色)、line(细线绘制:白色填充,墨色边缘,无阴影)、print(每个面平涂色调加墨线,类似印刷插图)和 night(黄昏,亮灯)主题下均可绘制,且每个主题字段都可覆盖:wobble 以手绘方式绘制墨线,halo 是底座投射到页面上的柔和阴影,accent 是每个主题中主体的颜色。examples/ 中的十八个示例是标准,其格式即为你需遵循的格式。

你只需编写一个东西:figure,即一个 .js 文件。内核 (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,约500px60–150≤ 240一到两个循环及指针响应
mini任何小空间:空状态、列表中的特性、404、设置区域1:1,160–240px15–40≤ 150一种安静的环境运动

然后阅读 references/concepts.md,并用一行写出概念,主题放在末尾:

名称. 地点及其中的事物。自动移动的内容。指针的作用。(对于mini:缺少什么。)主题。

从产品本身的世界中选取地点,而不是从示例中:港口、厨房、屋顶、书桌、温室、站台、发射台、街角都是 diorama。然后根据 figure 的所在位置选取主题,而非个人喜好:toy 用于需要温暖和色彩的产品页面;soft 用于编辑页面或奶油色页面;mono 用于拥有自己强调色(可将其作为 accent 传递)的产品 UI、文档或紧邻密集文本的任何内容;line 用于极简或技术性页面、深色文字配白色背景的品牌,或应保持低调的空状态;night 用于深色页面。如果用户有品牌色,则将其作为 accent 传入,该颜色会在每个主题中重新着色主体;第二个颜色通过 palette 传入。references/craft.md 包含每个主题添加的规则。

然后在任何代码之前编写部件列表:五行,每组一行,命名每个物体及其两到三个特征。地面(底座、区域、道路、水面),结构(竖立的物体:建筑、架子、树木),移动体(行驶、行走、转动或升降的物体),家具(填充边缘的物体:灯、锥桶、板条箱、长凳、栅栏),灯光(发光体:窗户、灯、信标)。每个部件都放置在其他部件上;没有悬浮物体。一个 hero 列表包含多达三十个物体,card 为十个,mini 为三个。该列表即是场景:如果读起来单薄,figure 也会如此。

如果有人可问,提供两到三个选项并等待。如果无人可问,选择静止帧最强的那个,并说明你选取了哪个。一个 diorama,一个地点,一个故事。需要标题才能被理解的场景尚不是一个概念。

2. 构建

  1. 阅读 references/craft.md。十条规则是让 diorama 看起来像一个地方而非一堆立方体的关键;违反任何一条的 figure 都未完成。
  2. 阅读 kit/diorama.js 顶部的索引(var Diorama 上方的注释)。它列出了你可以调用的所有内容。请勿阅读其下的代码。
  3. 阅读最接近你尺寸和主题的示例: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 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:一个框架式机器,内置凹槽,裸露线圈,风扇)。这些示例并非都是工厂,这是有意为之:diorama 可以是任何地方。
  4. 在工作目录中编写 figure 为 <name>.js,格式与示例一致:一个 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 保留的颜色,是品牌十六进制颜色替换的颜色,也是工作台色板实时重新着色的颜色。对于手绘的 line figure,可添加 wobble: 1.4(震颤的 CSS 像素:1.2 为钢笔,2.5 为毡尖笔)。
    • means: 一句话,≤ 140 字符,显示在舞台下方。说明场景展示的内容和移动的对象。
    • hint: 一行,≤ 90 字符,说明指针的操作和点击的操作(“悬停在火箭上查看其级数;点击控制室立即发射”)。页面会显示此提示,让访客知道可以互动,而 look.mjs 会按下它命名的内容。
    • title: figure 的名称,页面会显示在舞台上方。用户自己的 UI 中围绕 figure 的词语(标题、行、按钮)由他们自己编写;场景本身不携带任何文字。
    • camera: { az, el, pad },以度为单位。az 45 是等距默认值;30–40 在 3:2 hero 中显示宽阔底座。除非场景较高,否则将 el 保持为 35.264。
    • still: 循环中用于减少动效和缩略图的秒数。选择一个所有物体都处于有意义位置的时刻(卡车在码头,叉车抬起)。
    • 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 响应点击(点击是手机端的响应方式,因此 hero 或 card 应有一个可点击的对象:开关、呼叫,或悬停的孪生操作)。D.apart 在指针下拆解物体并将其还原。将 ctx.read 设置为一个简短的行,说明场景当前正在做什么('truck · at the dock'):页面会将其显示为读条,并且这是访客了解场景是一个工作模型而非循环的方式。references/motion.md 包含相关模式。
  5. 组装:node <skill>/scripts/build.mjs <name>.js 写入 diorama-<name>.html:包含工作台、内核和 figure。内核以插画师模拟深度的方式绘制 SVG(等距投影,每个面一种平涂色调,从场景后到前绘制部件,将阴影作为形状投射在地面上),因此页面无需渲染器、无需 WebGL 且不发送网络请求;绘图是矢量图,在任何尺寸下都清晰,并且页面可以为其设置样式。

3. 检查

  1. 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:穿过其他部件的运动部件;车辆穿过树木或汽车穿过公交车是需要修复的错误,而叉车在货架上或旗帜在其铰链上则是正常的。
  2. 阅读 references/look.md,然后阅读表单,并回答其问题。修复失败项,然后返回步骤 1。

look.mjs 需要浏览器;它会查找 Playwright 的浏览器,或者在此文件夹外部安装一次 playwright-core。如果没有浏览器,则在每次构建后运行 node <skill>/scripts/validate.mjs diorama-<name>.html,并按照 look.md 中“Without a browser”的描述进行查看。不要移交验证器拒绝的页面。如果你没有查看过,就不要说查看已完成。

4. 移交

按照用户的要求移交 diorama-<name>.html:当用户需要文件时,给出文件并说明其位置;否则,如果可能,将其发布为制品。然后,每行一项说明:

  • 概念:地点、移动内容、指针和点击的作用,以及主题(以及如何切换:在 figure 中使用 theme:,在页面中使用 ?theme= 和 ?accent=,在 Diorama.mount 中使用 { theme };工作台的色板可以实时重新着色主体);
  • 静止帧:哪个秒数,以及为什么选择那个时刻;
  • 适用位置(hero、card 或 mini)以及如何嵌入(references/react.md 用于 React 或 Next.js;其他地方使用一个包含内核和 figure 的普通 <script>,加上 Diorama.mount(fig, { el }));
  • 任何你无法验证的内容(没有 Node、没有浏览器),如实说明。

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 在所有五种主题中都是相同的
将品牌颜色粘贴到二十个部件上,或使用调色板名称绘制主体使用 pal.accent 绘制主体,并在声明中一次性将品牌十六进制颜色放入 accent;第二个颜色使用 palette: { cobalt: … }
只有悬停响应而没有手指操作为一个对象设置点击响应(ctx.pressed、ctx.active):悬停预览,点击确认(motion.md 中的“The press”)
一个 line figure 读起来像 CAD 导出文件在主题中添加 wobble: 1.4:墨线会像手绘一样弯曲和越过
因为底座“看起来脏”而关闭 halohalo 是将 diorama 放置在页面上的关键;在繁忙的背景下降低它(.1),但保留它
读条显示的内容与标题相同ctx.read 是用文字表示的时钟:相位、停止、计数,来自与定位部件相同的 T
在场景之后构建底座,或根本不构建首先使用 D.slab:阴影需要落脚点(规则 01)
场景读起来像一堆相同的立方体网格为每个对象赋予其独有的两到三个特征(规则 05)
一个包含八个物体的 mini一个对象,一种环境运动(concepts.md 中的“A mini”)
一个 hero 中所有物体都以相同节奏移动三个具有不同周期和相位偏移的循环;motion.md 中的“Loops”
一个拥有15种颜色的场景palette 保持10种颜色;通过色调和明度扩展它们(规则 03)
在代码中使用 CSS 选择器或 DOM APID 工具包是唯一允许的 API;不要触摸 DOM
编写 console.log 或 alert将状态写入 ctx.read 或通过 D.log 写入控制台
在 figure 中导入其他文件figure 是独立的;所有辅助函数都在 D.props 中
将像素值硬编码到主题中对需要它的图元使用 pal.* 属性,并在主题定义中覆盖它们

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相关技能