# 数据格式 ## 最小地铁图 ```json { "mode": "metro", "title": "研究方法地图", "subtitle": "示意分类,不表示时间或推荐排名", "routes": [ {"id":"qual","label":"定性","code":"A","color":"#208a87","stops":["interview","synthesis"]}, {"id":"quant","label":"定量","code":"B","color":"#3d64a3","stops":["survey","synthesis"]} ], "nodes": [ {"id":"interview","label":"访谈"}, {"id":"survey","label":"问卷"}, {"id":"synthesis","label":"综合证据","major":true} ] } ``` ## 顶层字段 | 字段 | 含义 | |---|---| | `mode` | `metro` 或 `timeline`,默认前者 | | `title`, `subtitle` | 主标题、解释性副标题 | | `eyebrow`, `footer` | 页眉分类、来源/语义/刻度说明 | | `routes`, `nodes` | 非空数组,下面说明 | | `layout` | 可选尺寸与布局参数 | | `theme.paper` | 背景色,`#RRGGBB`,默认米白 | | `links` | 可选明确关联,`{"from":"节点ID","to":"节点ID","label":"关系依据"}`;画为细灰箭头,不自动创造 | | `eras` | 时间图背景,`{"start":1800,"end":1900,"label":"阶段"}`;范围必须在时间轴内 | | `ticks` | 时间图的刻度数字数组,不得超出节点时间范围 | ## 线路 `id` 唯一;`label` 显示名称;`code` 用短字母或数字;`color` 为 `#RRGGBB`;`group` 是图例栏目标题;`stops` 是节点 ID 的有序列表,非空、同一线路内不重复。 所有线路的 `stops` 共同定义归属;没有节点侧的第二套 `routes` 字段。多条线路引用同一个 ID 就是换乘节点。所有节点至少属于一条线路。 可选 `offsets` 控制横向弯道,如 `[[0,0],[0.25,0],[0.45,-50],[0.75,-50],[1,0]]`。地铁图默认省略此字段,保持主干笔直。每对值是 `[纵向归一化位置,水平偏移像素]`,位置 0/1 为全图首/末事件,严格递增并限制在 0—1。端部保持最近值,相邻点以平滑三次曲线连接;站点按同一函数定位。偏移不是自动布线,过大的偏移会造成相撞或换序,需看图调整。 ## 节点 | 字段 | 含义 | |---|---| | `id` | 唯一、非空、稳定字符串 | | `label` | 主名称,默认 ID | | `detail` | 可选一行说明,不自动换行 | | `major` | `true` 时强调文字和站点 | | `order` | metro 排序优先值;只在满足线路先后约束的节点中生效,默认输入数组顺序 | | `time` | timeline 必需有限数字,负数年代需解释记年法 | | `label_side` | `left` / `right` 优先方向;冲突时可自动反向 | | `label_dy` | 标签垂直偏移像素;设置后不再尝试其他垂直偏移,仍可反向、移到侧栏 | 共享节点是所有所属线路上的同一事件;名称相似或发生时间不同的条目应使用不同 ID,再以明确关联连接。 ## 布局 | 字段 | 默认 | 含义 | |---|---|---| | `width` | 1320 | 需容纳全部线路、文字和侧栏 | | `lane_gap` | 86 | 相邻线路横向间距,最小 32 | | `row_gap` | 66 | metro 站点纵距,最小 36;高度按节点数计算 | | `font_size` | 17 | 节点字号,最小 8 | | `lane_order` | `routes` 顺序 | 所有线路 ID 的完整排列 | | `height` | 2050 | timeline 高度,metro 忽略 | | `time_scale` | 全范围线性 | timeline 分段映射 | 地铁图使用稳定拓扑排序,每个节点占一个纵向层级。当前版本不把独立节点压到同一行,也不做线路邻接的全局优化;可通过 `lane_order`、输入节点顺序和弯道进行编辑。 时间图每条线路按时间升序列出站点,同年事件允许并排,范围不能只有一个值。可用 `"time_scale":[[1800,0],[1900,0.28],[1950,0.59],[2000,1]]`。第一对必须为 `[最早节点时间,0]`,最后为 `[最晚节点时间,1]`,两列严格递增;相邻区段内线性插值。图中须注明压缩区段,脚本不自行决定压缩哪些年代。不能为避让修改年代。 ## 输出与返回值 - SVG:真实文字、路径和几何节点,保留 `data-route` / `data-node`,字体未嵌入。 - `.report.json`:尺寸、数量、节点坐标、标签侧向/偏移/估计包围框、提示列表。 - `label_needs_review`:估计标签碰撞、越界或穿越线路;要修正并看图复核。 - `overpass`:非成员线路从共享胶囊上方通过,是信息提示;只有圆环表示归属。 - `route_outside`:线路越界,需要调整偏移或加宽。 - 退出码:0 成功;1 输入/文件错误;2 `--strict` 发现待复核问题。报告不是像素级碰撞证明。 额外来源字段可放入节点或关联,渲染器忽略它们,源 JSON 应保留以便追溯。只把经过核实或用户明确给出的关系加入 `links`。