村界数据怎么下钻:从全市到单县的加载实测
技术专栏 · 数据处理 · 2026-10-15
地图下钻是村界应用的骨架交互:先看全市格局,点某个县,进去看村级细节。做顺了体感很轻,做不顺就是三件事打架——首屏加载 16 兆、点击后白屏半秒、连点两下地图串台。这篇拿江西宜春的两级真实包(全市包 + 10 个县级切片)把三笔账都算了出来:体积账、耗时账、状态账,数字全部来自本轮实测。
体积账:切片合计等于全市包,首屏却只要零头
宜春市包 16,184KB,解出 2,751 个村级面。把它按县级切成 10 份,每份就是一个县的下钻数据。切片体积从靖安的 374KB 到丰城的 3,423KB 不等:
| 县级切片 | gz 体积 | 县级切片 | gz 体积 |
|---|---|---|---|
| 丰城市 | 3,423KB | 宜丰县 | 1,471KB |
| 高安市 | 3,091KB | 樟树市 | 1,137KB |
| 袁州区 | 2,401KB | 万载县 | 1,210KB |
| 上高县 | 1,412KB | 铜鼓县 | 749KB |
| 奉新县 | 911KB | 靖安县 | 374KB |
| 10 片合计 16,179KB ≈ 全市包 16,184KB(拆分无损) | |||
切片合计与全市包只差 5KB——按县拆分是无损的,拼回去就是全市。首屏的账因此好算:默认只载全市包(16.2MB)是传统做法;下钻架构里首屏同样载全市包,但用户点进某县后,加载的是 0.4 到 3.4MB 的单县文件。给整套做前端适配时(像素坐标、抽稀),削减比例在 78% 到 97.6% 之间,越小的县省得越多。
耗时账:30 毫秒对 659 毫秒,差在哪三段
把加载拆成三段计时:读文件、gunzip 解压、逐要素解析。全市包 12 + 275 + 372,合计 659 毫秒;铜鼓县切片 2 + 10 + 18,合计 30 毫秒;最大的丰城市切片也不过 156 毫秒。三段里解压与解析占九成以上——它们都跟数据量成正比,切片小了它们就同比例缩小:
顺带一个数据自证的细节:每个县级切片的主导村级码前 6 位,恰好就是它自己的区划代码(铜鼓 360926、宜丰 360924、丰城 360981……十个切片十个码)。拿切片反查归属不靠文件名,靠数据本身就能对号,做下载后的自动注册很稳。
状态账:晚到的渲染必须作废
体积和耗时解决「快」,状态管理解决「稳」。下钻最常见的故障是连点:点铜鼓,数据还没回来,手快点了一下高安,两个异步回调先后落地——高安先渲染,铜鼓晚到又把地图拍回去。治法是给每次点击发一个递增令牌,回调回来先对令牌,不是最新就整包丢弃:
let navSeq = 0; // 全局递增令牌
function drillDown(countyFile) {
const seq = ++navSeq; // 本次点击的令牌
fetch(countyFile).then(r => r.json()).then(data => {
if (seq !== navSeq) return; // 期间又点了别处:整包丢弃
renderCounty(data);
});
}
// 配套:程序化改视野传 animate:false,直接定位不留跳变帧;
// 若应用有搜索直达,等索引建完再处理,否则首帧拿不到目标县。
这三条——令牌丢弃晚到渲染、视野直接定位、直达排在索引建成之后——是同一次竞态排查里一起挖出来的。它们平时看着多余,一旦用户开始快速连点就会全部发作,而且发作时没有任何报错。
预取还是按需:默认按需,空闲时按概率补
10 个切片全量预取等于把全市包重新拉一遍,移动端流量不友好,这个方案直接排除。默认按需:点谁加载谁,最坏 156 毫秒(丰城),体感就是一次即时切换。要再进一步的折中是概率预取——用户停留在市域视图时,空闲时间先预取点击概率最高的切片(通常是城区和大县,袁州、丰城这一档);进县之后顺手预取它的邻县。预取队列控制在两三个文件以内,带宽就守住了。
本文的两级数据不需要自己拆:村界商品本身就按市与区县两种粒度交付,出自同一批次,切分无损、拼回无损;更大范围用省包。拆出来的切片如果嫌顶点太多,瘦身阈值在《GeoJSON 太大?先抽点,再谈小数位》实测过;下钻之后做点位归属查询,网格索引的做法见《把1.4万座山峰落到村界:网格索引快了102倍》。
常见问题
- 地图下钻的数据该怎么组织?
- 每一级行政区一份独立文件。本文实测江西宜春:全市包 16.2MB,拆成 10 个县级切片后合计 15.9MB——拆分基本无损,但首屏从 16.2MB 降到单县的 0.4 至 3.4MB,最大削减 97.6%。切片按行政区划代码命名,点哪一级就取哪一份。
- 下钻加载一个县要多久?
- 本地实测三段合计:读文件、gunzip 解压、逐要素解析。铜鼓县切片 749KB 全程 30 毫秒,最大的丰城市切片 3.4MB 也只要 156 毫秒,对比全市包的 659 毫秒同降约 95%。浏览器里还要加一次网络往返,本地数字是下限,结论不变:切片越小越快。
- 快速连点两个县,地图会不会串?
- 不设防会串。先点的县后返回、后点的县先返回,晚到的渲染会把新视图拍回旧县。解法是递增加载序号做令牌:每次点击记下当前序号,异步回调回来先比对序号,不是最新就整包丢弃。配合地图视野用 animate:false 直接定位,跳变帧就消失了。
- 县级切片应该预取还是按需加载?
- 按需是默认答案:10 个切片全量预取等于把全市包又拉了一遍,移动端流量不友好。折中做法是空闲时按点击概率预取——用户看完市域视图后最常点城区或大县,把它们排在预取队列前面;切到某县后再预取它的邻县,下钻体验就近乎无缝。
- 去哪里拿按市、按县拆好的村界文件?
- 本站村界数据本身就按这套粒度交付:按省、按市、按区县三种粒度出自同一批次,字段与坐标系统一,天然构成下钻的三级数据源。本文实测的宜春市包与铜鼓等县级切片即是同批次产物,拆分无损,拼接回市域也不会出错。