# 人类文明里程碑 · 活页编年史 一个以 **Three.js** 为核心、艺术化呈现世界历史里程碑的三维网站。它以一只**活页本**为隐喻,把历史中里程碑式的人、事、物登记成一张张两面活页:正面是登记卡(编号 / 时间 / 地区 / 名称 / 描述),背面是程序化生成的"铅笔素描"。 ## 三种视图 | 视图 | 内容 | | --- | --- | | **活页本** | 皮革封面 + 金属活页环 + 20 张双面活页,翻页动画、纸张弯曲、堆叠阴影 | | **时间轴** | 20 张活页沿金色时间轴一字排开,选中卡片上浮并显示年代 | | **地理** | Cesium 三维地球:卫星影像 + 真实地形 + 国界/城市标注 + 词条便签标记 | ## 地理视图(Cesium) 地理视图使用 **Cesium**(懒加载,进入该视图才加载脚本),免费、无需 Ion token: - **影像/地形**:ESRI World Imagery 卫星影像(限制 ±85°)+ Esri World Elevation 3D 真实地形。 - **国界**:Natural Earth 50m,黑色单线。 - **国家/城市名**:Natural Earth + GeoNames 中文名,黑边黄字(`FILL_AND_OUTLINE`),按距离淡出,背面经深度测试隐藏。 - **词条便签**:DOM 覆盖层(非 billboard),贴地形高度,逆时针 45° 斜放、平滑曲线箭头;未选中金底黑字带黑边,选中黑底金字。 - **交互**:左键旋转、滚轮缩放(500 m ~ 8000 km)、右键原生 tilt(松手不回正)、中键回正(flyTo 动画)。 - **画质**:按设备像素比渲染(高分屏清晰)、FXAA + MSAA、地形 `maximumScreenSpaceError=2.0`。 - **兜底**:丢弃 ESRI 灰色 "Map data not yet available" 错误瓦片,自动回退父级放大。 ## 技术要点 - **Three.js**(ES 模块 + Vite)渲染全部三维内容,`OrbitControls` 供旋转/缩放。 - **程序化纹理**:纸张、皮革、活页孔、登记卡、素描全部由 Canvas 2D 即时生成,无需外部图片。 - **程序化素描**:18 种手绘风格速写(头骨、泥板、金字塔、人像、神庙、王冠、斗兽场、卷轴、骑士、帆船、地球仪、苹果、蒸汽机、自由钟、进化树、原子、和平鸽、火箭),带抖动线条与排线阴影,同一词条每次渲染结果确定一致。 - **双面活页**:正面用 `FrontSide`、背面用 `BackSide`(内容预先水平镜像),配合纸张柔性弯曲,翻页时自然显露背面素描。 - 数据(`src/data/entries.js`)包含 20 条真实历史里程碑,含经纬度与分类(人 / 事 / 物)。 ## 性能优化(已完成) - **纹理懒加载 + LRU**:页面 / 卡片纹理按需生成,引用计数 + LRU 释放(上限 40 页),启动只为可见窗口生成;时间轴卡片用独立低分辨率纹理池(256×358)。 - **按需渲染**:静止时停止重绘,动画 / 交互 / 状态变化时才渲染(含页面 z 过渡的 `isSettling` 判定)。 - **几何降级**:栈内页用极简几何(2 三角形),顶层 / 翻页页才用高分段;封面皮革曲面、活页环、铆钉均降低分段;时间轴卡片 24×6 → 12×3。 - **双面材质合并**:页面正反面合并为单 mesh(`gl_FrontFacing` 双纹理),draw call 减半;活页孔用 alphaTest 免透明排序。 - **Cesium 懒加载 + 后台预载**:首屏不加载 6MB 脚本,首帧后后台预载,地理按钮就绪前在循环切换中自动跳过。 - **地理数据 primitive 化**:7342 城市点/标签与约 240 国家名标签由 entity 改为 `PointPrimitiveCollection` / `LabelCollection`。 - **渲染分辨率**:DPR 上限 1.5、Cesium 关闭超采样、页面纹理关闭 mipmap、anisotropy 8→4。 - **射线检测节流**:hover 合帧到渲染循环,只测可见窗口对象(binder 当前页 ±1、时间轴可视窗口)。 - **gzip**:Nginx 开启 gzip(含 `application/octet-stream`),geojson 3MB→1MB、城市 641KB→182KB。 ## 运行 ```bash npm install npm run dev # 开发服务器 npm run build # 生产构建(dist/) npm run preview # 预览生产构建 ``` ## 部署 ### 1. 构建 ```bash npm run build ``` ### 2. 部署到 Web 服务器(hist.fukun.net) 站点托管在腾讯云 `62.234.90.54`(Ubuntu 24.04),静态文件放在 `hugo` 用户的 `~/hist` 目录,Nginx 指向该目录。 通过 SSH 打包上传(密钥见 `C:\Code\Claw\keys\tx-ubuntu-hugo.pem`): ```bash # Windows (Git Bash) / Linux SSHKEY="C:/Code/Claw/keys/tx-ubuntu-hugo.pem" tar czf - -C dist . | ssh -i "$SSHKEY" -o StrictHostKeyChecking=accept-new hugo@62.234.90.54 \ 'rm -rf ~/hist/* && tar xzf - -C ~/hist && echo 部署完成' ``` > Nginx 配置与 SSL 证书已就绪: > - 站点配置:`/etc/nginx/sites-available/hist.fukun.net`(root `/home/hugo/hist`) > - SSL 证书:`/etc/nginx/ssl/hist.fukun.net_bundle.crt` + `hist.fukun.net.key`(TrustAsia) > - 证书本地备份:`C:\Code\Claw\nginx\hist.fukun.net\` ### 3. 推送代码到 Git ```bash git push origin main ``` 远程仓库:`git@git.fukun.net:fukunee/Hist.git`(SSH)。 ### 4. 验证 ```bash curl -s -o /dev/null -w "%{http_code}\n" https://hist.fukun.net/ # 应输出 200 ``` ## 操作 - **拖动** 旋转视角,**滚轮** 缩放 - 地理视图:**左键拖拽** 旋转、**滚轮** 缩放、**右键拖拽** 倾斜环视(松手不回正)、**中键** 回正 - **← →** 或底部按钮 翻页(翻面查看背面素描) - 点击 活页 / 时间轴卡片 / 地球标记 选中词条 - 顶部按钮或按键 **1 / 2 / 3** 切换 活页本 / 时间轴 / 地理 视图 ## 目录结构 ``` src/ main.js 入口 core/App.js 编排器:渲染、灯光、相机、视图切换、拾取 scene/binder.js 活页本(封面、环、双面活页、翻页动画) scene/timeline.js 时间轴视图 scene/CesiumGlobe.js 地理视图(Cesium 地球、国界、城市、词条便签) textures/pages.js 纸张 + 登记卡/素描两面纹理 textures/sketch.js 程序化素描生成器 data/entries.js 历史词条数据 ui/overlay.js HTML 覆盖层 ui/loading.js 加载遮罩 utils/ 缓动 / 文字精灵 scripts/ 截图与验证辅助(开发用) ``` ## TODO / 后续规划 - [ ] **纹理懒加载**:书页与时间轴卡片的 Canvas 纹理改为按需 / 增量生成。当前启动时一次性生成全部纹理(每条词条正反两面),在 1000 条词条压力测试下启动耗时约 6 秒;懒加载后应降到约 1 秒。 - [ ] **活页本分册**:为全部词条增加分册(分卷)机制——按历史时期或主题分组,顶部提供分册导航与切换,活页本只展示当前分册的内容,降低单册厚度、便于浏览。 - [ ] **时间轴时期划分**:时间轴轴线上标注中西方历史时期刻度(如中国朝代:夏商周 / 秦汉 / 隋唐 / 宋元明清;西方:古典时代 / 中世纪 / 文艺复兴 / 启蒙运动 / 工业革命等),作为背景衬托。 - [ ] **词条插入时间轴**:词条按其 `timeNumeric` 真实时间位置插入时间轴(当前为等距排列),使时期刻度与词条位置相互对应。 - [ ] **词条结构考究与排版优化**:重新审视 `entries.js` 数据模型(补充年代精度、文明圈、影响、关键词等字段),并优化登记卡正面排版(信息层级、留白、装饰细节)。 - [ ] **性能进一步优化**:继续排查渲染 / 显存 / 加载瓶颈(已做:纹理懒加载、按需渲染、几何降级、双面材质、gzip 等)。 - [ ] **边界测试修复**:尾页(第一页 / 最后一页)前后的边界情况,在地理视图与时间轴视图存在 bug,待修。 - [ ] **时间轴清晰度**:时间轴视图当前偏模糊,需排查(可能是卡片低分辨率纹理 256×358 或渲染分辨率导致)。