Files
rogerwang2008 f1888fbaf8 feat: PDF 导出脚本支持三页合一
逐页渲染 page1/page2/page3 并用 pypdf 合并为单个 PDF,默认输出 dist/三页demo.pdf;
--page 改为可多值的 --pages(保留旧名),每页各自校验四边 1em 与 Zpix 字体。
README 同步导出用法与各页说明。
2026-11-11 04:18:11 +08:00

136 lines
6.4 KiB
Markdown
Raw Permalink 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.
# 《关于「甲子」的虚构故事》公众号推送 Demo
一个 28 列 × 44 行的汉字文字画 Demo。黑底、每格一个汉字,空白处由淡色「天」铺满;画面包含晚霞云、落日、飞鸟、天线与城市楼群,上方以整格扣出的黑色标题框居中呈现「关于「甲子」的虚构故事」。
项目规划为三张类似页面,当前实现第 1 页(`page1.html`)、第 2 页(`page2.html`)与第 3 页(`page3.html`)。
## 效果概述
- 28 列 × 44 行,严格按字符网格排布,全页文字统一字号。
- 空白格自动填充淡色「天」,形成低对比背景纹理。
- 元素按层绘制:云 → 落日 → 飞鸟 → 天线 → 楼群。楼群最后绘制,保证太阳在无楼处仍保留完整圆弧。
- 标题区域按整格对齐扣空,并叠放黑色面板,居中显示白色标题。
- 使用 Zpix 像素字体;正文行通过负字距补偿,把单字步进压回 1em。
## 目录结构
```
.
├─ page1.html # 第 1 页入口
├─ page2.html # 第 2 页入口
├─ page3.html # 第 3 页入口
├─ pyproject.toml # uv 环境与导出依赖
├─ uv.lock # 依赖锁定
├─ scripts/export_pdf.py # PDF 导出脚本
├─ assets/
│ ├─ css/
│ │ ├─ common.css # 三页共用:字体、骨架、网格、标题框
│ │ ├─ page1.css # 第 1 页配色
│ │ ├─ page2.css # 第 2 页配色
│ │ └─ page3.css # 第 3 页配色与前景标题
│ ├─ js/
│ │ ├─ text-scene.js # 共享文字画渲染引擎
│ │ ├─ page1.js # 第 1 页场景数据
│ │ ├─ page2.js # 第 2 页场景数据
│ │ └─ page3.js # 第 3 页场景数据
│ └─ fonts/zpix.ttf # Zpix 像素字体
└─ references/a.html # 原始参考页
```
## 运行
直接打开 `page1.html` 即可。若需通过本地服务器预览:
```bash
python -m http.server 8000
# 第 1 页 http://localhost:8000/page1.html
# 第 2 页 http://localhost:8000/page2.html
# 第 3 页 http://localhost:8000/page3.html
```
## 多页结构
现有页面:
- `page1.html`:完整日落城市文字画,空白处铺淡色「天」。
- `page2.html`:空白处铺淡色「墙」;底排「地」,其上以「桌」「椅」摆出桌子与椅子,桌面立「酒杯」「烛」与火,右下角「桶」包「酒」作酒桶,右上角「链」「笼」「灯」「穗」拼出灯笼,墙上以「框」包「图」作画框,前景为「酒水单」与两列曲目。
- `page3.html`:空白处铺淡色「黑」的演职员表;含 36 个演职员 nametag、电线、麻雀、草、消防栓与下半屏火山,nametag 与「演职员表」四周的空白格不铺背景。
共用与专属:
- `common.css`、`text-scene.js`:三页共用的页面骨架、网格、标题框与渲染引擎。
- `pageN.html`、`pageN.css`、`pageN.js`:每一页的入口、配色与场景数据。
新增页面时复制 `page1.*` 三件套,修改 `pageN.js` 中的数据与 `pageN.css` 配色,并按顺序引入 `common.css`、`pageN.css`、`text-scene.js`、`pageN.js`。
## 导出 PDF
使用 Playwright(由 uv 管理)导出,页面尺寸为 30em × 46em:28 × 44 格的画面,四周各留恰好 1em。默认把三张页面合成一份三页 PDF。
```bash
uv sync
uv run python scripts/export_pdf.py # 三页 → dist/三页demo.pdf
uv run python scripts/export_pdf.py --page page2.html -o dist/page2.pdf
uv run python scripts/export_pdf.py --pages page1.html page3.html -o dist/选页.pdf
uv run python scripts/export_pdf.py --em 16 -o dist/三页demo-16.pdf
```
`--page` / `--pages` 按给定顺序逐页渲染后用 pypdf 合并,只传一个页面即得到单页 PDF。
脚本优先调用本机 Edge / Chrome;若都未安装,可先下载 Playwright Chromium:
```bash
uv run playwright install chromium
```
导出页为黑底满幅,画面距上、下、左、右边界各 1em;脚本会在导出前逐页校验该边距。默认 `--em 24` 时每页输出 720 × 1104 px(约 190 × 292 mm)。
## 调整指南
### 构图(assets/js/page1.js)
| 数据 | 含义 |
| --- | --- |
| `clouds` | 云:三行 3/5/3 的云形,x/y 为最宽一行的左上角 |
| `sun` | 落日:逐行圆形切片,数组顺序对应顶部的红到底部的黄 |
| `birds` | 飞鸟:每只占 2 格(麻雀 / 喜鹊 / 乌鸦) |
| `antennas` | 天线:单列「线」,从 y 向下叠 h 格 |
| `buildings` | 楼群:x/y/w/h,n 对应 `.bld-n` |
| `title` | 标题文案、高亮词、起始行、行高、左右留格数 |
坐标为 0–27 列、0–43 行;越界会直接抛错提示。
### 样式
共用样式(`assets/css/common.css`):
- 整体字号:`.scene` 的 `font-size`,所有元素统一继承。
- 标题:`.title-panel`(黑色矩形)与 `.title-panel .title`(文字样式)。
页面样式(`assets/css/page1.css`):
- 背景「天」:`.sky`。
- 云:`.cloud` 的明度与 `.cloud-*` 的色相。
- 落日:`.sun` 的整体明度(当前为原色 80%),`.sun-t1` 至 `.sun-t17` 为逐行色阶。
- 飞鸟:`.bird-sparrow`、`.bird-magpie`、`.bird-crow`。
- 天线:`.ant`(深色款为 `.ant-dark`)。
- 楼群:`.bld` 与 `.bld-1` 至 `.bld-8`。
### 第 2 页(assets/js/page2.js)
`block(x, y, w, h, text, cls)` 按矩形铺字:桌面与桌腿、靠背/座面/椅腿、枪口/枪身/握把都由若干矩形拼出,坐标按格对齐;配色见 `page2.css` 的 `.table`、`.chair`、`.gun`、`.ground`。
### 第 3 页(assets/js/page3.js)
通过 `glyphs` 数组放置任意背景字:`{ text, x, y, cls, vertical }`,坐标仍按格对齐。前景标题 `.credits` 由页面脚本追加,可在 `page3.css` 中调整字号与位置。
## 实现说明
- `text-scene.js` 先建立 28×44 网格并全部填「天」,再按页面数据覆盖元素;同 class 的连续字符合并为单个 `span` 输出。
- 标题区把对应格子清空,并在同一位置叠放绝对定位的黑色面板;边缘与字符整格对齐,不会出现半个字。
- Zpix 单字步进为 13/12 em,因此 `.line` 使用 `letter-spacing: -0.083333em` 补偿,保证 28 列恰好落在 28em 宽内。
## 字体许可
`assets/fonts/zpix.ttf` 为第三方 Zpix 像素字体,版权归原作者所有;使用或分发前请遵循其原始许可说明。