Files
Hist/README.md
T

156 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 人类文明里程碑 · 活页编年史
一个以 **Three.js** 为核心、艺术化呈现世界历史里程碑的三维网站。它以一只**活页本**为隐喻,把历史中里程碑式的人、事、物登记成一张张两面活页:正面是登记卡(编目号 / 时间 / 地区 / 名称 / 描述),背面是程序化生成的"铅笔素描"。
## 三种视图
| 视图 | 内容 |
| --- | --- |
| **活页本** | 皮革封面 + 金属活页环 + 全部词条双面活页(正面登记卡、背面素描),翻页动画、纸张弯曲、堆叠阴影 |
| **时间轴** | 全部词条活页沿金色时间轴等距排开,上方常显主题、轴下方常显时间;点击/左右键选中并居中 + 翻面(纸张弯曲动画) |
| **地理** | Cesium 三维地球:卫星影像 + 真实地形 + 国界/城市标注 + 词条便签标记 |
## 地理视图(Cesium)
地理视图使用 **Cesium**(懒加载,进入该视图才加载脚本),免费、无需 Ion token:
- **影像/地形**:ESRI World Imagery 卫星影像(限制 ±85°)+ Esri World Elevation 3D 真实地形。
- **国界**:Natural Earth 110m,黑色单线。
- **国家/城市名**:Natural Earth(10m 城市点,直接使用其 `name_zh` 中文名),黑边黄字(`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 即时生成,无需外部图片。
- **程序化素描**:53 种手绘风格速写(化石、泥板、金字塔、人像、神庙、王冠、斗兽场、卷轴、骑士、帆船、地球仪、苹果、蒸汽机、自由钟、进化树、原子、和平鸽、火箭、书、桥、旗帜、天平、剑、头盔、齿轮……),带抖动线条与排线阴影,同一词条每次渲染结果确定一致。
- **双面活页**:正面用 `FrontSide`、背面用 `BackSide`(内容预先水平镜像),配合纸张柔性弯曲,翻页时自然显露背面素描。
- 数据(`src/data/entries.js`)包含 182 条真实历史里程碑,含经纬度、分类(人 / 事 / 物)与档案式编目号。
- **编目号**:每页登记 `NO.{时间}-{地区}-{序号}`,如 `NO.BCE3-AFETNE-I0001`。时间=BC/AD 两位世纪,或 BCE1–BCE4 地质年代(1万/10万/100万/1000万年前);地区=大洲码+国家码+方位码(如 AFETNE=非洲·埃塞俄比亚·东北部);序号前缀 E/P/T/I/B(事件/人物/学说技术/文物/建筑)。
- **时间轴交互**:拖拽左右滑动、滚轮缩放;点击卡片 / 左右键 / 底部按钮 选中并平滑居中 + 翻面(带纸张弯曲动画),选中另一张时其它翻到背面的卡片自动翻回正面。
- **文字清晰度**:文字精灵 2 倍超采样栅格化;页面纹理以完整分辨率(768×1075)上传,避免降采样发糊。
## 性能优化(已完成)
- **纹理懒加载 + 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`。
- **渲染分辨率**:Three.js 像素比上限 2(`min(devicePixelRatio, 2)`)+ MSAA 抗锯齿、Cesium 开 FXAA,三视图清晰;页面纹理关闭 mipmap、anisotropy 8→4。
- **时间轴专项**:拖拽期间暂停纹理生成(避免滑动时同步 canvas 绘制掉帧);时间轴视图关闭阴影贴图、灯光 5→2;刻度线合并为单个 LineSegments。
- **射线检测节流**:hover 合帧到渲染循环,只测可见窗口对象(binder 当前页 ±1、时间轴可视窗口)。
- **gzip**:Nginx 开启 gzip(含 `application/octet-stream`),geojson 3MB→1MB、城市 641KB→182KB。
## 翻页交互
- **空间点击翻页**:按命中点的空间左右半区判定方向——书脊右侧向前翻、左侧向后翻,翻页过程中也不受页索引错位影响。
- **松开触发**:左键「松开且未拖拽(≤4px)」才翻页;拖拽旋转视角不会误翻页。
- **首尾回卷 + END 页**:最后一页再向前进入 END 页——末页翻到左侧露出其背面素描;END 页向前回卷到第一页,第一页向后直接快进到 END 页,首尾闭环,底部导航联动显示「END」。
## 运行
```bash
npm install
npm run dev # 开发服务器
npm run build # 生产构建(dist/)
npm run preview # 预览生产构建
```
生成 / 切换词条数据(跑完重新 `npm run build`):
```bash
python scripts/gen_entries.py # 182 条真实词条(含坐标去重、编目号、素描分配)
python scripts/gen_entries_stress.py # 1000 条压力测试数据
```
## 部署
### 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
```
## 操作
- **活页本**:拖动旋转、滚轮缩放;点击书页右侧向前/左侧向后(松开触发);**← →** / 底部按钮翻页;第一页再向后 / 最后一页再向前回卷到 END 页
- **时间轴**:拖拽左右滑动、滚轮缩放;点击卡片 / **← →** / 底部按钮 选中并居中 + 翻面
- **地理**:左键拖拽旋转、滚轮缩放(右键 tilt、中键回正);点击标记选中
- 底部导航栏按钮(或按键 **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 程序化素描生成器(53 种)
data/entries.js 历史词条数据(182 条)
ui/overlay.js HTML 覆盖层
ui/loading.js 加载遮罩
utils/ 缓动 / 文字精灵
scripts/
gen_entries.py 生成真实词条(坐标去重、编目号、素描分配)
gen_entries_stress.py 生成 1000 条压力测试数据
region_codes.py 地区编码 + 条目类型分类
analyze/ascii/colorascii/shot/verify 开发辅助
public/
world-countries.geojson 国家边界(Natural Earth 110m)
world-cities-zh.json 城市点(Natural Earth 10m,中文名)
```
## TODO / 后续规划
- [ ] **国家/城市名贴地(参考便签)**:当前国家名、城市名标签在地形起伏处“钉地”不准(`CLAMP_TO_GROUND` 表现不理想)。需参考词条便签的做法,用 `Cesium.sampleTerrain` 显式采样地形高度后设置标签锚点高度,使其真正贴合地形表面。
- [x] **纹理懒加载**:已完成(见「性能优化」——可见窗口按需生成 + 引用计数/LRU 释放)。
- [ ] **活页本分册**:为全部词条增加分册(分卷)机制——按历史时期或主题分组,顶部提供分册导航与切换,活页本只展示当前分册的内容,降低单册厚度、便于浏览。
- [ ] **时间轴时期划分**:时间轴轴线上标注中西方历史时期刻度(如中国朝代:夏商周 / 秦汉 / 隋唐 / 宋元明清;西方:古典时代 / 中世纪 / 文艺复兴 / 启蒙运动 / 工业革命等),作为背景衬托。
- [ ] **词条插入时间轴**:词条按其 `timeNumeric` 真实时间位置插入时间轴(当前为等距排列),使时期刻度与词条位置相互对应。
- [ ] **词条结构考究与排版优化**:重新审视 `entries.js` 数据模型(补充年代精度、文明圈、影响、关键词等字段),并优化登记卡正面排版(信息层级、留白、装饰细节)。
- [ ] **性能进一步优化**:继续排查渲染 / 显存 / 加载瓶颈(已做:纹理懒加载、按需渲染、几何降级、双面材质、gzip 等)。
- [x] **首尾边界回卷**:活页本第一页 / 最后一页 / END 页边界已处理,首尾闭环。
- [x] **渲染清晰度**:像素比上限 2 + MSAA / FXAA 抗锯齿,三视图不再发糊。