DESIGN.md · diff
git:20260909.2b048ee to git:20260909.8bdca93
7 added, 7 removed. Audit A to A.
# 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 五步研究流程。左侧是标题、方法说明与研究入口,中间是带样本的仪器,右侧是有界馆藏面板,下方是五站导航。五座等距固定三维门架对应五站流程,数量不随馆藏增长。
- 桌面组合画布为 1586×992,按 `min(innerWidth / 1586, innerHeight / 992)` 等比缩放。`experience` 高度为 460svh,`stage` 为固定在视口的 100svh 区域,页面根元素与 body 使用 `overscroll-behavior: none` 关闭系统边界回弹,弹窗保留独立滚动。常规最小高度为 480px,手机为 560px;短横屏取消最小高度约束,将五站导航保留在视口内。
+ 桌面组合画布铺满视口,三维相机与 DOM 控件按视口重新构图;紧凑布局保留独立的手机和平板断点。`experience` 高度为 460svh,`stage` 为固定在视口的 100svh 区域,页面根元素与 body 使用 `overscroll-behavior: none` 关闭系统边界回弹,弹窗保留独立滚动。常规最小高度为 480px,手机为 560px;短横屏取消最小高度约束,将五站导航保留在视口内。
当前 CSS 的主要色值:
| 角色 | 值 |
| ------------- | --------- |
- | 背景 | `#050606` |
- | 主文字 | `#edece8` |
- | 次文字 | `#aaaead` |
- | 弱文字 | `#858b88` |
- | 结构线 | `#414644` |
- | 状态与焦点 | `#80ed95` |
+ | 背景 | `#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,并经灰度处理。右侧卡片先在首页选择研究,三维样本、标题、类型和 Open study 入口同步更新;点击三维样本的射线拾取会触发当前研究入口。键盘使用的 `#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` 当前包含 **19** 项。初始 `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`,只为当前页创建结果节点,页码最多五个;19 项无筛选时为 6、6、6、1 四页。首页长度固定,完整目录数据的下载量、内存和筛选计算仍随馆藏增长。
原位 `#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。