滚动式3D落地页(适用于任何物体)
本技能用于构建一个3D对象作为主角的单页落地页。该对象固定于内容后方,在用户滚动时改变姿态、渲染风格和环境背景。适用于任何可以展示的物体:酒瓶、耳机、椅子、吉他、手表、汽车、建筑模型、雕塑、老式相机、香水瓶、工具或玩具。
参考案例为toppervenom.com,由Evil Rabbit制作(原文链接),该技能即源于此项目。页面展示了一款90年代Topper篮球运动鞋;其3D模型并非扫描,而是通过AI从档案资料和生成的多视角图像重建而成。页面起始为技术蓝图样式(白色线框在蓝色网格上),然后呈现真实材质、展示尺寸和部件、变换颜色,最后旋转结束。该运动鞋仅为示例;真正复制的是页面的构建方法和品质水平。 每个项目都应选择自己的视觉概念、幕序序列和最适合物体的揭示效果(请参见下文“适配物体”)。
这些页面为何如此出色(请开始前阅读)
品质并非来自技术栈。toppervenom.com仅约90KB的HTML/CSS/JS加Three.js(据作者称,页面由AI一次性生成):无框架、无GSAP、无打包工具。品质来自以下五点,每个项目决策应服务于其中至少一点:
- 一个真实且精心准备的3D资产。 具有摄影纹理的扫描、精心制作的AI重建(如toppervenom),或一个细节丰富、干净、轻量且比例真实的模型。若模型质量差,其他一切都无法补救。→
references/3d-capture.md,references/3d-alternatives.md - 摄影标准的渲染。 三点照明、环境贴图、中性色调映射、接触阴影和校正的材质(扫描通常带有错误的金属度,使皮革看起来像塑料)。→
references/rendering.md - 贯穿至每个细节的艺术指导概念。 toppervenom的“技术蓝图”:网格、尺寸标注、等宽字体,加载器显示“PLOTTING DRAWING Nº 01”,滚动条显示“REV. 0 — BLUEPRINT”。一切都讲述着同一个故事。→
references/art-direction.md - 基于物理的运动,而非关键帧。 姿态按场景声明;JS使用平滑插值进行插值,并通过指数衰减缓冲每个值,从而营造重量感和惯性。→
references/choreography.md - 证明3D价值的Shader效果。 线框到实体的揭示通过一个扫描平面的物体实现,具有菲涅尔效应的鬼影表面,基于亮度的重新着色。这些是视频无法实现的。→
references/shaders.md
如果用户要求“类似这样的效果”,实际工作是:获取一个优质模型 + 选择一个概念 + 耐心调整。模板负责解决工程问题。
适配物体(不要复制运动鞋)
模板包含一个示例序列(蓝图→尺寸→部件→揭示→数字→起源→结尾),但物体的形状及其历史决定了构图、效果和幕序。在编写姿态之前,请按此表定位物体:
| 物体形状 | 示例 | 构图 | 最佳揭示效果 | 典型幕序 |
|---|---|---|---|---|
| 水平长形 | 运动鞋、汽车、吉他、刀、钢笔、火车 | 物体一侧,文字另一侧;纯侧影用于尺寸标注 | 沿长度方向扫描(从头部到尾部) | 技术侧影,部件细节,速度或使用场景 |
| 垂直/旋转体 | 酒瓶、香水、台灯、花瓶、奖杯、建筑 | 物体居中或置于三分之一处,文字两侧双列;仰视角度用于高潮 | 从下到上扫描(“填充”)或横向切割 | 轮廓,材质或内容,起源,使用仪式 |
| 紧凑/盒形 | 耳机、相机、音箱、手表、游戏机、珠宝 | 大特写(scale 1.4-2)像微距镜头般遍历物体 | 分解(爆炸视图)或对角线扫描 | 设计,内部/组件,材质,规格 |
| 平面/正面阅读 | 书、唱片、画作、板子、卡片、平板电脑 | 短旋转(±0.4 弧度)以显示厚度;避免长时间边缘展示 | 凝聚的点状,或“浮现”的绘画 | 正面,背面,纹理细节,背景 |
| 有机/雕塑 | 雕塑、食物、植物、化石、玩具 | 缓慢宽广的旋转,大量轮廓光 | 点云→表面,或具有菲涅尔的鬼影 | 形状,纹理,历史,人体尺度 |
| 组合件 | 家具、机器、模型、模块化产品 | 3/4高视角,整体在画面内 | 滚动分解:每个部件沿其轴分离并返回 | 整体→分解→部件逐个→组装 |
| 大尺度 | 房屋、建筑、项目地、轮船 | 更远的相机,“模型”在桌上旋转 | 按楼层垂直扫描,剖面切割 | 选址,布局,剖面,材质 |
同时根据物体选择视觉概念,而非默认。“技术蓝图”适用于所有设计或制造之物;葡萄酒可能需要“酒庄卡片”;雕塑可能需要“博物馆目录”;设备可能需要“实验室”;复古之物可能需要“复古目录”。完整菜单见 references/art-direction.md,替代效果(分解、点状、切割、填充)见 references/shaders.md。
工作流程
按顺序执行以下阶段。在编写代码前,与用户确认阶段1和2的决策,因为它们会影响后续所有内容。
阶段 1 — 简报和概念(与用户共5分钟)
提问或推断:
- 什么物品及其材质(皮革、玻璃、金属、哑光塑料、布料)。材质决定如何捕捉及照明。
- 5-8幕故事。每幕为一个部分和一个物体姿态。典型示例:展示→方案/尺寸→解剖(部件)→揭示→数字→起源/历史→结尾。
- 视觉概念,即统一整体的隐喻。不要默认复制“蓝图”:选择对该产品有意义的隐喻。
references/art-direction.md中有一个概念菜单(技术蓝图、博物馆卡片、实验室、90年代目录、时尚社论、工业爆炸图),包含其调色板、字体及如何将其逐一转换为3D。 - 真实内容。数据、尺寸、材质、历史和引用。参考页面之所以感觉真实,是因为它们使用了原始目录和扫描的真实数据。若无数据,请索取;不要为真实产品编造规格。
- 语言(西班牙语/英语)及是否有颜色变化。
阶段 2 — 获取3D模型
这是对最终质量影响最大的阶段。使用此决策树并阅读相应参考:
用户是否有实物?
├─ 是 → 扫描它(references/3d-capture.md)
│ ├─ 哑光/有纹理物体(运动鞋、食物、石头、木材、布料)→ 手机或相机摄影制图
│ ├─ 闪亮、黑色或透明物体 → 临时哑光喷雾 + 摄影制图,或建模
│ └─ 非常小/精细(珠宝、线缆)→ 微距摄影制图或建模
└─ 否 → 替代方案(references/3d-alternatives.md)
├─ 有制造商的CAD/STEP文件 → 转换并添加纹理
├─ 多角度优质照片 → AI图像转3D(Meshy、Tripo、Rodin、Hunyuan3D、TRELLIS)+ 清理
├─ 几何形状(瓶子、罐子、灯、家具)→ 在Blender中建模(旋转/拉伸),1-4小时
├─ 通用产品 → 购买或下载带许可证的(Fab、Sketchfab、CGTrader、Poly Haven)
└─ 无法获取模型 → 程序化/风格化物体(lathe、SVG拉伸、点状、线稿)
无论来源如何,模型需经过优化管线(references/asset-pipeline.md):清理,递减至100-300k三角形,纹理2048-4096为WebP,Meshopt压缩,真实比例,正确原点及方向,以及一个用于线框的单独高度递减网格。这个细节非常重要:密集网格的线框看起来像灰色噪声,而非图纸。
此步骤有一个现成脚本:scripts/prepare-model.sh <输入.glb|.obj|.fbx> <名称>。它会生成优化的 models/<名称>.glb 和用于线条的 models/<名称>-wire.glb。以示例Stratocaster为例,它从22.2 MB缩减至1.8 MB。
扫描或手工制作模型。 递减的线框网格适用于扫描,其中边缘是噪声。在手工制作模型(CAD、Sketchfab、Blender)中,递减网格会变成跨表面的长三角形,看起来像网格而非绘图。此时应使用 wireMode: 'edges' 作用于主网格,并设置 wireModel: null,不生成线框文件。这样读取为技术图纸,并节省一个文件。
Sketchfab下载:需登录(免费账户)。若使用内置浏览器,让用户登录并在下载前确认名称、大小和格式(GLB)。将原始文件保存到单独的 source/ 文件夹中,并在页脚标注作者(CC BY)。
阶段 3 — 从模板构建项目
将 assets/template/ 复制到项目文件夹。内容如下:
| 文件 | 功能 |
|---|---|
index.html | 结构:固定背景(网格+纸),固定<canvas>,固定<svg>覆盖层,加载器,导航,进度条,颜色选择器,以及带有姿态属性的页面部分(data-ry、data-x、data-reveal…)。 |
styles.css | 视觉系统:标记,流式排版使用clamp(),CSS网格,纸张背景,具有模糊的显示,缓动曲线,移动端适配。 |
main.js | 引擎:渲染器,灯光,带进度的加载,显示和颜色变化的shader,线框和鬼影效果,阴影,滚动编排,带弹簧的拖拽,SVG覆盖层(尺寸标注和标注框),计数器,颜色变化。所有内容均可在文件开头的CONFIG中配置。 |
无需构建。任何静态服务器均可运行(npx serve、python -m http.server)。因使用ES模块,不支持file://协议。Three.js通过jsDelivr固定版本在importmap中加载;生产环境建议复制到vendor/并添加modulepreload(见references/performance.md)。
无需模型即可测试:index.html?model=<某个.glb的URL>,或无参数时查看替代的程序化物体。一个好的测试glb是KhronosGroup/glTF-Sample-Assets中的MaterialsVariantsShoe.glb。
阶段 4 — 将模型调整至场景
在 main.js → CONFIG 中:
orient:旋转直到物体Y轴朝上、X轴为长轴(例如[0, 0, -Math.PI/2]用于将竖着的吉他放平)。旋转在测量模型之前应用,因此包围盒、尺寸标注、sweepDir、标注框和分解都始终在已旋转的空间中表示。使用?debug查看轴。realSizeCm:最长边的实际尺寸,单位厘米。由此计算出所有显示的尺寸标注。sweepDir:揭示扫掠的方向。应遵循物体的自然“阅读”方向:长形物体沿长度方向([1,0,0]或[0,0,1]),瓶子或建筑从下往上([0,1,0]),紧凑物体对角线([0.3,0.3,1])。callouts:部件位置,作为包围盒的小数(f,0..1)或模型的精确坐标(p,以其单位)。代码将其吸附到最近顶点。从上到下排序,以免线条交叉。使用?debug时,点击模型即可在控制台打印其精确小数坐标。colorways:为每个变体定义深/浅色(若物体无变体,则移除选择器)。shader根据亮度重新着色,并保留饱和细节;若物体本身为饱和色,设置keepSaturated: 0。- 页面部分:自由添加、删除或重新排序
<section>。引擎会读取任意数量和顺序的部分姿态。 - 特殊情况的引擎选项:
procedural: () => Object3D通过代码构建物体,而非加载glb。wireMode: 'edges'仅绘制图纸线框。适用于硬表面、CAD或程序化物体。extraKeys: ['screen']+onFrame(cur, dt, t)用于由页面部分(data-screen)控制的定制效果。例如,屏幕点亮、灯光或盖子打开。- 使用
data-explode的分解:每个部件根据其userData.explode = [x,y,z]移动(若无则远离中心)。 - 逐个部件:
userData.noRecolor(忽略颜色变化)、userData.noWire(不在线框平面显示)、userData.keepPbr(引擎不修改其材质)。 recolorOnly: ['BodyMaterial']:仅这些材质(按glb名称)应用颜色变化。在吉他上,仅绘制琴身,保留护板、琴颈和金属件的原样。keepPbr: true保留手工模型的PBR(真实金属、带透明涂层的清漆)。默认情况下,引擎会修正扫描和AI重建的虚假金属度,这会破坏精细模型。wireColors: [纸张背景0的颜色, 纸张背景1的颜色]和edgeColor使线框平面适应任何概念,例如专利纸墨水而非白蓝两色。背景的两个状态(backdrop__grid和backdrop__paper)仅名称而已:可样式化为层压板→舞台、橱窗→夜景等。data-rz(旋转)用于停放长物体,如吉他放在架子上。地面阴影在停放时会自动关闭。
- **
…(已截断以翻译)