DESIGN.md · git:20260911.65f566f · 2026-09-11 · sha256 b4333de005f59346

DESIGN.md git:20260911.65f566fA

Immutable. This exact content is served forever at /api/v1/blob/b4333de005f59346.

# Design Teardowns 设计与实现说明

## 实现范围

本说明对应 `teardowns/index.html`、`_gallery/beamline.js`、`beamline-3d.js`、`beamline.css` 与 canonical `catalogue.js`。产品行为见 [PRODUCT](PRODUCT.md),交付状态和验证记录统一见 [README](README.md#验证与交付)。

## 构图与视觉语言

光束线用同一台仪器表达 Capture、Measure、Reconstruct、Verify、Archive 五步研究流程。左侧是标题、方法说明与拆解入口,中间是带预览的仪器,右侧是有界案例档案库面板,下方是五阶段导航。五座等距固定三维门架对应五阶段流程,数量不随案例档案库增长。

桌面组合画布铺满视口,三维相机与 DOM 控件按视口重新构图;紧凑布局保留独立的手机和平板断点。`experience` 高度为 460svh,`stage` 为固定在视口的 100svh 区域,页面根元素与 body 使用 `overscroll-behavior: none` 关闭系统边界回弹,弹窗保留独立滚动。常规最小高度为 480px,手机为 560px;短横屏取消最小高度约束,将五阶段导航保留在视口内。

当前 CSS 的主要色值:

| 角色          | 值        |
| ------------- | --------- |
| 背景          | `#050912` |
| 主文字        | `#f3f6f2` |
| 次文字        | `#aebbc0` |
| 弱文字        | `#7f929b` |
| 结构线        | `#42505a` |
| 状态与焦点    | `#8bffb0` |
| Measured 图例 | `#f2544d` |
| Inferred 图例 | `#48d7d3` |

字体从本地加载:Oswald 用于主标题与站名,IBM Plex Mono 400 通过 CSS 别名 Plex 用于导航、数据和卡片文字,GallerySerif 使用 `GallerySerifSC-400.woff2`,按仓库说明对应 Noto Serif SC 子集,并以 Songti SC 和通用 serif 回退。许可路径见 [NOTICE](NOTICE)。

## 三维世界与渲染边界

运行时是本地 `vendor/three.min.js`,其 `REVISION` 为 160。一个 `WebGLRenderer` 渲染主光束线;程序另建环境烘焙和全屏后处理用的辅助 scene。

主世界包含挤出的倒角金属门架、实例化螺钉与轨枕、轨道、124 节输送带、滚轮、发射器、台车、纸面预览、玻璃和网格、三维准星、灯光及光束。金属使用 `MeshStandardMaterial`、程序生成的纹理及 PMREM 环境反射;场景有阴影和雾,HDR render target 经亮部提取、模糊与合成输出 bloom。环境贴图由程序里的照明面生成,主世界没有使用静态照片作建筑底板。

这里的实时「物理世界」指几何、基于物理的材质、光照、遮挡与射线求交。轨道运动是进度插值,没有质量、刚体、重力、摩擦或碰撞动力学求解。光束从发射器孔径指向准星,对预览背板和门架做射线求交后截断到首个不透明命中;该光学示意也不是完整光线追踪模拟。

预览使用当前选中案例档案库的 hero 图(按案例目录约定优先取 `screenshots/hero.jpg`,否则取 `assets/actual-hero.jpg`,失败时回退案例档案库封面),加载后绘入 CanvasTexture,并经灰度处理。右侧卡片先在首页选择案例,三维预览、标题、类型和 View teardown 入口同步更新;点击三维预览的射线拾取会触发当前拆解入口。键盘使用的 `#specimen-access` 是投影到预览中心的 DOM 链接;图像、网格和准星本体都在 Three.js 中。

## 五阶段运动

原生滚动距离归一化后只更新 `targetProgress`;站点链接把目标设为目的站,并应用 `navigation.maxSpeed` 限速。唯一的运动控制器维护 `progress` 与 `velocity`,在 `tick()` 中以秒为单位、用 `response = 38` 的临界阻尼解析式跟随目标,并处理方向反转和到站收敛。`setStage(progress)` 同时更新读数、导航状态和三维场景,行程中保留最近实际到达的工位,经过或抵达下一工位后才更新阶段文字,避免中点提前切章。原生滚动结束后保留输入位置,不自动回拉或归位;只有点击工位执行精确停靠,新输入可立即接管。场景按该进度插值,不再叠加另一条行程缓动;鼠标视差的独立阻尼不参与台车行程。

五个工位等距固定,停靠点直接由各门架的实际挤出几何中心生成,台车按这五个位置在 z 方向插值,总行程为 44 个世界单位。`travel = carriageZ - stops[0]` 同时驱动 124 节实例化输送带;节距为 0.62,带节循环回到轨道另一端。滚轮角度按 `travel / 0.23` 更新,反向行程会反转。相机使用相对预览的固定构图偏移跟随,校准停靠点后仍保持预览在画面中的位置;紧凑布局按 world scale 换算跟随距离。预览和输送带由同一位移推进,没有另一个独立计时动画。

预览角度、网格显隐、准星显隐、红青参考层间距及各门架灯光由同一进度决定。灰度预览在纹理生成时已处理,红青参考层是研究方法示意,不计算像素差。

桌面鼠标视差采用按帧间时间计算的阻尼;滚轮、触摸、指针按下或相关导航键可接管站点导航,后续滚动继续提供目标。页面不可见时取消待渲染帧;通常按状态变化请求渲染,只在鼠标视差尚未收敛时继续请求帧,没有持续空闲摆动。

## 一个归档面板

canonical `catalogue.js` 当前包含 **20** 项。初始 `featured.js` 固定顺序为 `shopify-editions,pear,shopify-editions-spring26,moonshot,comet,latrix`,每项由 canonical 全字段派生。生成与检查命令、数量同步的维护方式见 [README](README.md#维护案例档案库)。

`ensureCatalogue()` 通过动态 script 加载 `_gallery/catalogue.js`,缓存已加载数据和进行中的 Promise。打开 Archive 弹窗,或操作搜索、分类、排序、分页会触发加载;滚动到第五阶段只改变站点。失败会清理加载 Promise,并提供可重试错误状态。

`renderArchive()` 先用六项 featured 展示初始展览。完整目录加载后,Curated order 仍按 featured 的 slug 顺序取 canonical 中的六项,再追加 catalogue 中其余项目,保留其原序;元数据始终取自 canonical。默认第一页因此在初始加载、完整目录载入及面板展开之间保持一致。标题排序是单独选项,按标题字母顺序排列全部匹配项。

搜索覆盖标题、中文标题、简介、类型和类别,分类及搜索变化重置到第一页。`pageSize = 6`,只为当前页创建结果节点,页码最多五个;20 项无筛选时为 6、6、6、2 四页。首页长度固定,完整目录数据的下载量、内存和筛选计算仍随案例档案库增长。

原位 `#archive-panel` 与弹窗内的面板是同一个元素。打开时将它移入 `#archive-slot`,关闭时通过原位置的注释锚点放回;query、category、sort、page 都由同一控制器持有。使用原生 dialog,支持关闭按钮、对话框外点击、初始焦点与关闭后焦点回归。

桌面原位面板采用三列两行,平板原位面板与手机弹窗采用两列三行,每页最多六项。Latrix 与 EasyCode 的类型分别采用 canonical 的 `Web · Digital identity` 和 `Web · Learning product`,研究依据见 README 表格。

## 响应式、减弱动态与静态 fallback

| 条件                                            | 当前代码行为                                                                             |
| ----------------------------------------------- | ---------------------------------------------------------------------------------------- |
| 宽度超过 1200px 且宽高比至少 1.25               | 桌面等比构图,三维相机视角 32°,允许轻微鼠标视差。                                       |
| 宽度不超过 1200px 或宽高比低于 1.25             | 紧凑布局与相机,视角 38°,关闭鼠标视差;平板案例档案库以两列三行展示。                         |
| 紧凑布局且高度不超过 760px                      | 隐藏原位案例档案库,使用 Archive 弹窗。                                                        |
| 高度不超过 560px                                | 横屏重排标题、入口及五阶段导航,弹窗内滚动保留卡片完整尺寸。                               |
| 宽度不超过 600px                                | 手机相机视角 43°,隐藏原位案例档案库,通过 Archive 弹窗展示两列三行结果。                      |
| 减弱动态                                        | 关闭 CSS 动画和过渡,导航直接到站,三维进度按五阶段取整;按变化重绘,没有固定低帧率循环。  |
| 初始化失败、预览图像加载失败或 WebGL 上下文丢失 | 隐藏 canvas 与投影入口,显示可点击的 Latrix 静态封面;控制器可运行时仍可使用方法和案例档案库。 |
| JavaScript 完全禁用                             | 显示四个研究直链与外部仓库目录,不提供完整本地检索。                                     |

渲染分辨率设置桌面 1.7、紧凑布局 1.5 的像素比上限,并按约四百万绘图像素缩减;像素比另有 0.75 下限,因此任意视口下并非硬性像素预算。页面还提供可见焦点、搜索与筛选标签、当前站点状态、结果播报及更高对比度媒体查询。

WebGL 上下文恢复后重新生成环境贴图与绘图尺寸;丢失期间的窗口变化不会把隐藏画布的零尺寸写入渲染器。预览图片未完成时保持静态入口,完成后恢复场景。

## 软件渲染兼容

通过真实 WebGL renderer 名称识别 SwiftShader、llvmpipe 等软件后端。软件模式保留真实几何、纹理、五阶段移动与拾取,限制绘制预算为 196,608 像素,关闭多重采样、HDR 光晕、阴影和环境贴图预计算,使用漫反射材质并预编译着色器,降低逐像素开销。硬件模式保持原有构图、材质与后处理配置。此选择不依赖测试环境或 URL 开关;诊断记录 renderer 名称与实际 profile。