GIS数据GIS DATA

村界数据怎么下钻:从全市到单县的加载实测

技术专栏 · 数据处理 · 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 毫秒。三段里解压与解析占九成以上——它们都跟数据量成正比,切片小了它们就同比例缩小:

全市包与三个县级切片的加载耗时对比:659 毫秒对 30 至 156 毫秒
本地实测(Node,SSD 直读),浏览器还要加一次网络往返——本地数字是下限,切片越小越快的结论不变。

顺带一个数据自证的细节:每个县级切片的主导村级码前 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 个切片全量预取等于把全市包又拉了一遍,移动端流量不友好。折中做法是空闲时按点击概率预取——用户看完市域视图后最常点城区或大县,把它们排在预取队列前面;切到某县后再预取它的邻县,下钻体验就近乎无缝。
去哪里拿按市、按县拆好的村界文件?
本站村界数据本身就按这套粒度交付:按省、按市、按区县三种粒度出自同一批次,字段与坐标系统一,天然构成下钻的三级数据源。本文实测的宜春市包与铜鼓等县级切片即是同批次产物,拆分无损,拼接回市域也不会出错。