TopoJSON 丢了 transform,坐标全变成整数 7823
文件从 20 MB 压到 3 MB,转换后却画不出任何东西,坐标是 7823、4210 这样的整数。
现象
用 topojson.feature(topology, topology.objects.districts) 转回 GeoJSON,
得到的坐标是 [7823, 4210]、[7826, 4208] 这样的整数,
而不是 [116.397, 39.909]。
地图上要么看不到内容,要么所有要素挤在 [0,0] 附近。
原始 TopoJSON 的顶层有 transform 字段,但被某个处理脚本删掉了,
或者经过了「只保留 objects 与 arcs」的裁剪。
原因
TopoJSON 为了压缩体积,把坐标量化成整数存储,并在顶层记录还原参数:
{
"type": "Topology",
"transform": { "scale": [0.001, 0.001], "translate": [73, 3] },
"arcs": [...],
"objects": { ... }
}
还原公式是 lon = x * scale[0] + translate[0],
lat = y * scale[1] + translate[1]。
丢了 transform,topojson-client 只能原样返回量化整数。
排查过程
- 打印 TopoJSON 的顶层键,确认是否存在
transform。 - 打印
arcs[0][0],若为整数数组就是量化坐标。 - 看
objects里有没有bbox,可用它反推 translate。 - 与原始 GeoJSON 的 bbox 对比,若差值正好等于 scale × 量化值,即可确认。
console.log(Object.keys(topology));
// ['type', 'arcs', 'objects'] <- 缺 transform
console.log(topology.arcs[0][0]);
// [7823, 4210] <- 量化整数
const g = topojson.feature(topology, topology.objects.districts);
console.log(g.features[0].geometry.coordinates[0][0]);
// [7823, 4210] <- 未还原
解决方案
回到生成端重新导出,不要在转换脚本里删 transform。
确实只剩量化坐标时,可以用 bbox 反推参数。
# 用 topojson 命令行重新量化,保留 transform
npx topojson -q 1e4 -s 1e-3 -o districts.topo.json districts.geojson
# 检查输出是否带 transform
node -e "const t=require('./districts.topo.json');console.log(!!t.transform)"
前端兜底:已知原始数据范围时,手工补出 transform,
再交给 topojson.feature。
// 原始数据范围:经度 73~135,纬度 3~54;量化位宽由 arcs 最大值决定
const bbox = [73, 3, 135, 54];
const maxQ = 1e5; // 量化系数
const scale = [(bbox[2] - bbox[0]) / maxQ, (bbox[3] - bbox[1]) / maxQ];
const translate = [bbox[0], bbox[1]];
const fixed = { ...topology, transform: { scale, translate } };
const geo = topojson.feature(fixed, fixed.objects.districts);
console.log(geo.features[0].geometry.coordinates[0][0]);
// [116.39743, 39.90923] 量级恢复正常
验证
还原后第一个坐标应落在经度 73~135、纬度 3~54 之间;
与原始 GeoJSON 抽样 10 个顶点比对,误差应小于 scale/2,即 0.00062 度(约 69 米)。
const c = geo.features[0].geometry.coordinates[0][0];
console.assert(c[0] > 73 && c[0] < 135 && c[1] > 3 && c[1] < 54, '坐标未还原');
console.assert(Math.abs(c[0] - 116.397428) < 0.001, '与原始值偏差过大');
适用版本
| 库 / 工具 | 版本 | 说明 |
|---|---|---|
| TopoJSON 格式 | 1.0 | transform 为可选,缺失时坐标为量化整数 |
| topojson-client | 3.1.x | feature() 依赖 transform 还原 |
| topojson-server / cli | 3.x | -q 量化,-s 保留 transform |
经纬志(2026)。《TopoJSON 丢了 transform,坐标全变成整数 7823》。https://www.jingweizhi.com/cookbook/topojson-missing-transform.html(访问日期 2026-11-03)。