资讯动态

世界国家GeoJSON数据处理全流程:清洗压缩与可视化实践

发布时间:2026/10/14 4:06:56 来源:尧图企业网站定制
简介面向WebGIS开发者和地理信息学习者的世界国家GeoJSON数据集提供全球各国边界及属性信息可用于地图可视化、地理空间分析与离线地图应用开发。压缩包共2000个文件以JSON/GeoJSON格式为主整体仅2.1MB轻量易用数据涵盖FeatureCollection结构、WGS84坐标系统、各国家多边形边界及名称等属性适合前端地图库如Leaflet、Mapbox直接加载解析。已有4700余人学习下载。除基础国家轮廓外资料还包含美、俄、澳等国的细分区域GeoJSON方便进行局部细化分析配合常见GIS工具即可完成数据筛选、坐标转换或行政区划统计是教学、科研和商业项目的实用基础数据。同时内含的边界精度与来源说明有助于使用者评估不同数据的适用场景避免因坐标系或边界细节造成误用。1. 世界国家的 GeoJSON 不是一份文件而是一套数据处理流程某个周末接了个大屏需求把整个世界地图按用户访问量着色。设计师从某个数据资源站拖来一份“世界国家geojson”打开有几十MB加载到浏览器里白屏他又换了一份结果国度位置镜像。问题不在工具而在大家默认“GeoJSON拿来就能用”。这篇笔记想讲清楚世界地图、世界国家geojson、各国地图json数据这三者的常见形态它们本质上是同一批内容的不同产物都需要过一遍选型、清洗、压缩和验证。你会看到可运行的HTML、Python和JavaScript命令也能看到我在生产环境踩过的5个坑。新手能照着出一版可线上跑的底图数据熟手可以跳过“能跑”直接看参数和边界取舍。好从数据结构开始。2. 先拆格式世界国家 GeoJSON 的 FeatureCollection 与坐标规则2.1 Feature 与 MultiPolygon怎么读懂一个国家的数据结构GeoJSON 是一种开放的地理数据交换格式世界国家数据通常以 FeatureCollection 装起来。不要把 FeatureCollection 当成一张表它更像一行行“带坐标带属性的要素”。每个要素的 geometry 描述一个国家的地理形状properties 存国家名、ISO 代码、人口等业务字段。大多数国家的几何类型是 Polygon 或 MultiPolygon。如果一个国家的主体由多块不相连的土地组成比如沿海列岛、飞地就用 MultiPolygon 表示。换句话说Polygon 是“一个封闭区域”MultiPolygon 是“多个封闭区域的集合”。阅读坐标时你要先分清层级否则清理边界时很容易把一个环当成一个国界。下面是一段精简示例表达一个多边形的标准嵌套结构{ type: FeatureCollection, features: [ { type: Feature, properties: { name: 示例岛国, iso_a3: XXX }, geometry: { type: MultiPolygon, coordinates: [ [[[120.0, 30.0], [121.0, 30.0], [121.0, 31.0], [120.0, 31.0], [120.0, 30.0]]] ] } } ] }可以这样理解 coordinates在 MultiPolygon 里最外层是一个数组里面的每个元素是一个多边形每个多边形又是一个环数组环数组至少要有 4 个坐标点因为最后一个点必须和第一个点相同才能闭合。如果环没有闭合渲染端会自动补线但在后期做面积统计时会得到错误结果所以自己生成数据时一定要保留闭合点。属性部分通常长这样name_en、iso_a3、continent、pop_est、economy。不同的数据源字段名千差万别有NAME大写的也有name:zh的因此清洗的第一步不是修改坐标而是先把属性字段列出来看看。2.2 坐标顺序与范围为什么数据画出来会左右翻转世界上大多数 GeoJSON 数据遵循 RFC 7946 标准坐标数组必须写成[经度, 纬度]也就是 longitude 在前latitude 在后。很多人在手动修补的时候习惯写[纬度, 经度]一旦混入文件渲染出来的地图就会左右镜像或上下颠倒而且很难排查。另一个常见坐标系问题是投影坐标。GeoJSON 本身要求使用 WGS84 经纬度EPSG:4326但如果原始数据来自某个投影坐标系直接丢给前端会显示成一条斜线。你在拿到数据后可以检查第一个坐标点的数值一般来说经度绝对值不超过 180纬度绝对值不超过 90如果看到坐标值为[400000, 4300000]这样的大数基本可以断定是投影坐标需要先做坐标转换再进入后续环节。2.3 数据源选型精度、体积和许可证一起看关于“世界国家 geojson 从哪来”可靠做法是使用公开的全球行政边界数据集。我平时在选择数据源时只看四个维度几何精度、文件体积、属性完整度和许可证。表格如下数据源类型典型体积顶点密度适用场景主要注意点极简全球数据0.3~3 MB每国几百到几千个点Web 大屏、快速原型小岛和飞地可能被删中等精度全球数据5~20 MB每国几千到几万点省级粒度以上展示需要简化后才能加载高精度全球数据50~200 MB每国几十万点离线分析、出图必须做简化容差控制按行政区拼接数据不定边界对不齐特定国家内部分区跨区域相邻边界重叠我一般优先选择中等精度且带 ISO 3166-1 三字码的数据因为后续做国家着色、点击高亮和按洲聚合都方便。许可证也要提前确认如果项目要打包进商业产品尽量规避那些明确“仅供学习”的派生数据。最后一招是从标准 SHP 格式自己转换字段保留最完整但你要自己面对编码、坐标顺序和属性表切割的问题。如果你手头只有一份 SHP 文件转换也不是难事。常见做法是用命令行工具 shp2json 或 Python 封装转换时注意字段名可能被截断到 10 个字符还要指定输出编码为 UTF-8。转换完毕后用下一节提到的体检脚本检查坐标范围和要素数再决定是否需要简化。2.4 用一段脚本快速体检数据无论数据从哪里来拿到文件后我先跑一个体检脚本确认它是有效的 FeatureCollection、要素数量是否达到常见全球国家的 190~250 个并打印第一个要素的属性。import json with open(world_countries.geojson, encodingutf-8) as f: data json.load(f) print(type:, data.get(type)) features data.get(features, []) print(feature count:, len(features)) if features: print(first properties:, features[0].get(properties)) geom features[0].get(geometry) print(first geometry type:, geom.get(type) if geom else None)逻辑说明这段代码不依赖第三方库读取文件后分别输出顶层类型、要素数、第一个要素属性和几何类型。如果feature count只有几十个说明这不是完整的全球数据如果geometry type是 None说明首条要素可能是占位信息需要跳过或补几何。把这段脚本保存为check_geojson.py后续每做一次清洗都重跑一遍能快速发现问题。3. 用世界国家 GeoJSON 跑通一个最小可用的地图页面现在数据已经通过体检你可以开始搭建第一个能点击、能悬停、能着色的页面。这一章用最轻量的方式把世界国家geojson加载进浏览器并做一次离线预览。3.1 本地目录与 Leaflet 最小页面我习惯把数据文件、脚本文件和库文件放在同一个目录里避免跨域问题。假设你已经下载了开源地图库 Leaflet并把对应的leaflet.css和leaflet.js放进vendor/leaflet/页面就可以这样写!DOCTYPE html html head meta charsetutf-8 title世界国家 GeoJSON 最小渲染/title link relstylesheet hrefvendor/leaflet/leaflet.css style#map { width:100%; height:90vh; background:#aad3df; }/style /head body div idmap/div script srcvendor/leaflet/leaflet.js/script script const map L.map(map).setView([20, 0], 2); fetch(world_countries.geojson) .then((res) res.json()) .then((data) { L.geoJSON(data, { style: { color: #2c3e50, weight: 1, fillColor: #ecf0f1, fillOpacity: 0.6 }, onEachFeature: (feature, layer) { const name feature.properties.name || feature.properties.iso_a3; layer.bindTooltip(String(name)); } }).addTo(map); }) .catch((err) console.error(加载 GeoJSON 失败:, err)); /script /body /html逻辑说明setView([20, 0], 2)里的数组是[纬度, 经度]这是 Leaflet 的 API 约定和 GeoJSON 文件里的坐标顺序正好相反很多人在这里被绕晕。地图库加载数据后L.geoJSON会把每个 Feature 转成对应的矢量图层style控制边界颜色、线宽和填充透明度。onEachFeature是给每个国家绑定鼠标悬停名称的钩子bindTooltip接收一个字符串。参数说明weight: 1号线的宽度在 2 级缩放下足够看清国界fillOpacity: 0.6会让国家颜色半透明方便叠底图。如果你需要给每个国家按指标着色可以在style里按feature.properties动态返回颜色。注意直接用file://打开这个 HTML 时浏览器通常不允许本地文件发起 fetch 请求。你需要在目录里开一个本地服务cd /path/to/your/project python3 -m http.server 8000然后访问http://localhost:8000/在页面中选择对应 HTML 即可。如果使用前后端分离的开发环境记得把 GeoJSON 文件放在能被静态托管的目录下。3.2 用 Python 先画一张预览图确认边界没有翻转浏览器出来后如果地图是空白的你需要一个更快的方式定位几何问题。我的习惯是用 Python 直接把 GeoJSON 画成 PNG这个过程不依赖任何地图库一分钟就能看出边界是否完整。import json import matplotlib.pyplot as plt with open(world_countries.geojson, encodingutf-8) as f: data json.load(f) fig, ax plt.subplots(figsize(16, 8)) def draw_polygon(rings, ax): for ring in rings: xs [p[0] for p in ring] ys [p[1] for p in ring] ax.plot(xs, ys, color#2c3e50, linewidth0.5) for feature in data[features]: geom feature[geometry] if not geom: continue if geom[type] Polygon: draw_polygon(geom[coordinates], ax) elif geom[type] MultiPolygon: for poly in geom[coordinates]: draw_polygon(poly, ax) ax.set_aspect(equal) ax.set_xlim([-180, 180]) ax.set_ylim([-90, 90]) plt.tight_layout() plt.savefig(preview.png, dpi100, bbox_inchestight) print(已输出 preview.png请打开检查)逻辑说明matplotlib的plot直接把环上的坐标点连线set_aspect(equal)保证经纬度比例一致避免地图拉长。如果数据坐标写反x 轴范围会落在[-90, 90]附近图像会明显横向压缩一眼就能看出来。参数说明linewidth0.5适合全球范围避免国界线条太粗xlim和ylim要按 GeoJSON 坐标标准设如果混入[lat, lng]画出来的图形会旋转 90 度。3.3 验证要素顺序前几个国家的名字和代码要符合预期渲染正常不代表数据可用。接下来检查每个国家的属性主键和要素数量确保整个数据是按国家划分而不是按碎块划分。python - PY import json data json.load(open(world_countries.geojson, encodingutf-8)) features data[features] print(要素数:, len(features)) for f in features[:5]: props f[properties] print(props.get(name), |, props.get(iso_a3)) PY逻辑说明这里用内联 Python 一次性输出前五个国家。如果前五项是若干个洲际边界或若干条“国际争议线”混在一起说明这份数据不是“世界国家”粒度而是更底层的边界线数据需要重新选择。3.4 从“能显示”到“能着色”一个按指标上色的示例页面能显示后实际项目往往需要根据国家统计数据上色。常见做法是把pop_est这类数值归一化后映射到颜色。你可以把style改为style: (feature) { const pop feature.properties.pop_est || 0; const alpha Math.min(1, pop / 1000000000); return { color: #2c3e50, weight: 1, fillColor: rgba(41,128,185,${alpha}), fillOpacity: 0.8 }; }逻辑说明alpha是人口与 10 亿的比值人口越多颜色越深。这个写法只是一个主题真实项目中你可以换成 GDP、访问量、订单数等指标。需要注意的是GeoJSON 数据里的pop_est并不是实时人口数据年份可能偏旧统计口径也随数据源变化。点击高亮也是地图业务的标配。你可以在onEachFeature里给每个图层绑定事件onEachFeature: (feature, layer) { layer.on(click, () { layer.setStyle({ fillColor: #e74c3c, fillOpacity: 0.9 }); }); layer.on(mouseout, () { layer.setStyle({ fillColor: #ecf0f1, fillOpacity: 0.6 }); }); }逻辑说明setStyle只会修改当前图层的样式不影响其他边界。如果项目里需要支持多选建议同时维护一个已选中要素集合避免每次点击都重涂。4. 数据清洗属性标准化、边界简化与国际代码主键4.1 清点属性表并处理缺失主键世界国界数据在真实项目里一定不是拿来即用的。常见问题包括字段大小写不统一、中英文名混排、ISO_A3为空等。第一步把 properties 全部抽到内存表里快速找出哪些要素缺主键。import json import pandas as pd with open(world_countries.geojson, encodingutf-8) as f: data json.load(f) rows [] for idx, feat in enumerate(data[features]): props feat[properties] rows.append({ idx: idx, name: props.get(name) or props.get(NAME) or , iso_a3: props.get(iso_a3) or props.get(ISO_A3) or , iso_a2: props.get(iso_a2) or , continent: props.get(continent) or , pop_est: props.get(pop_est) or 0, has_geom: feat.get(geometry) is not None }) df pd.DataFrame(rows) print(要素数:, len(df)) print(空 ISO_A3 数量:, df[iso_a3].eq().sum()) print(空几何数量:, (~df[has_geom]).sum()) print(df.head(10).to_string(indexFalse))逻辑说明iso_a3是 ISO 3166-1 三字代码如USA、CHN越是不同数据源混合越要把它作为 JOIN 主键因为地图数据源和业务数据表通常都带这个字段。空ISO_A3的要素要先补上否则后续点击国家、按洲聚合都会失联。参数说明这段代码容忍了name和NAME两种大小写如果你的数据源字段名是ADMIN改一行即可。不要把name当主键同一国家在不同数据源里可能有十几个别名。4.2 批量写入标准化属性并输出新文件主键清点完成后把之前收集的字段回写到 feature 的 properties同时清掉那些容易干扰前端渲染的冗长字段。clean_feature_ids set(df[df[iso_a3].ne()][idx]) for idx, feat in enumerate(data[features]): props feat[properties] props.clear() if idx not in clean_feature_ids: props[name] str(props.get(name) or Unknown) props[iso_a3] N/A continue row df.iloc[idx] props[name] row[name] props[iso_a3] row[iso_a3] props[iso_a2] row[iso_a2] props[continent] row[continent] props[pop_est] row[pop_est] with open(world_clean.geojson, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse) print(已写出 world_clean.geojson)逻辑说明props.clear()会把原始 properties 完全清空再按统一 schema 重写这样前端读取时无需处理兼容性问题。对于缺失iso_a3的要素这里给一个N/A避免页面因字段为 null 导致String()报错。4.3 用 Douglas-Peucker 简化边界控制文件体积如果你的数据有 20MB浏览器可能要花几秒解析。使用 Shapely 的simplify方法可以在保持轮廓基本形状的同时砍掉大量顶点。import json from shapely.geometry import shape with open(world_clean.geojson, encodingutf-8) as f: data json.load(f) tolerance 0.01 # 单位是经纬度度约 1 公里量级 def simplify_feature(geometry, tol): if geometry is None: return None geom shape(geometry).simplify(tol, preserve_topologyTrue) if geom.is_empty: return None return geom.__geo_interface__ for feat in data[features]: geom feat[geometry] if geom: feat[geometry] simplify_feature(geom, tolerance) if feat[geometry] is None: feat[geometry] geom # 简化失败时保留原几何 with open(world_simplified.geojson, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse)逻辑说明simplify(tol, preserve_topologyTrue)使用 Douglas-Peucker 算法tol越大保留的顶点越少。preserve_topologyTrue意味着算法在删除点时尝试保持多边形拓扑避免产生自相交或相邻国家之间出现破洞。参数说明tolerance0.01是在 WGS84 经纬度坐标系里直接操作的简化容差赤道附近大约对应 1 公里。做全球地图的 Web 展示我通常用 0.01~0.05 度如果只是做 2 级缩小的世界轮廓0.1 度也可以接受。需要小心的是容差太大会把海上的小块陆地吞掉常见的是“国家看起来缺了一个角”。需要注意simplify不会自动处理孤岛与主边界之间的拓扑。如果简化后出现某个岛悬空在错误位置多半是原始几何有重复点或未闭合环要用buffer(0)修复。4.4 按面积阈值过滤飞地和碎片高精度数据里常常包含几十个小岛或飞地在低缩放级别几乎看不见却拖累数据体积。对小面积多边形做过滤时要注意保留不小于阈值、但在语义上重要的飞地。from shapely.geometry import shape, MultiPolygon min_area 0.0001 # 经纬度平方度 def filter_small_parts(geometry, min_area): if geometry is None: return None geom shape(geometry) if geom.geom_type Polygon: return geometry if geom.area min_area else None if geom.geom_type MultiPolygon: keep [p for p in geom.geoms if p.area min_area] if not keep: return None if len(keep) 1: return keep[0].__geo_interface__ return MultiPolygon(keep).__geo_interface__ return geometry for feat in data[features]: geom feat[geometry] if geom: feat[geometry] filter_small_parts(geom, min_area)逻辑说明min_area用经纬度平方度作为近似值赤道附近 0.0001 平方度大约对应 100 平方米量级绝大部分小礁石会被去掉。这里把一个 MultiPolygon 拆开后过滤再拼回 MultiPolygon。参数说明阈值需要根据你的应用场景动态调整。如果是全球级精度的展示建议保留所有有名称属性的陆地如果是移动端碎石地图阈值可以再放大十倍。千万不要用固定比例尺下的像素面积阈值那会受投影影响非常大。4.5 清洗后必做的三件事清洗完不是直接交付我习惯做三件检查第一重新跑一次第 2 章的体检脚本确认要素数没有少第二打开 preview.png 看是否有某个国家消失第三用wc -c world_simplified.geojson看文件大小如果还超过 10MB继续调大 tolerance 或改用下一章的 TopoJSON。5. 世界国家 GeoJSON 高频踩坑边界异常、坐标顺序、加载卡顿排查这一章是我在多个可视化项目里复盘出的问题清单。每一条都按“现象、原因、解决”展开你可以直接对着描述排查。5.1 地图左右镜像像照了镜子现象预览图里亚洲在西、美洲在东整个地图水平翻转。原因GeoJSON 文件里的坐标被写成了[纬度, 经度]和 RFC 7946 标准相反。有些导出工具会自动交换有些不会。解决写一个递归交换坐标的脚本只对最内层的数字对生效。import json with open(wrong_order.geojson, encodingutf-8) as f: data json.load(f) def swap_pair(coords): if isinstance(coords[0], (int, float)): return [coords[1], coords[0]] return [swap_pair(part) for part in coords] for feat in data[features]: geom feat[geometry] if geom: geom[coordinates] swap_pair(geom[coordinates]) with open(fixed_order.geojson, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse)逻辑说明递归函数遇到数字对就交换[lat, lng]遇到嵌套列表则继续向下处理。这样无论 Polygon 还是 MultiPolygon 都能修复。执行后再用前面的 Python 预览脚本确认xlim范围落在[-180, 180]。5.2 某个国家整体消失或出现镂空现象预览图里某个区域是空白浏览器点击该区域也拿不到 Feature。原因该要素的几何类型不合法最常见的两种情况环没有闭合或者 Polygon 的坐标数组顺序倒了也包括数据源本身在该区域就不是以国家边界形式提供而是以“争议线”或“空白占位”存在。解决先用 Shapely 检查每个要素的is_valid再用buffer(0)修复。from shapely.geometry import shape, mapping for idx, feat in enumerate(data[features]): geom feat[geometry] if not geom: continue g shape(geom) if not g.is_valid: repaired g.buffer(0) feat[geometry] mapping(repaired) print(修复要素:, idx, feat[properties].get(name))逻辑说明buffer(0)会把自相交的环拆成有效多边形还会补齐闭合点。mapping()把 Shapely 对象转回 GeoJSON 字典。修复后再次检查要素数应该与修复前一致。注意某些低质量数据会把“海峡中线”“争议区域范围”也作为一个 Feature 放进去这类要素在业务上不是国家最好手工剔除不要在代码里做自动判断。5.3 浏览器白屏控制台报读不到坐标现象页面加载到一半就卡住控制台提示读不到feature.geometry.coordinates。原因不是所有 Feature 都有 geometry。清洗阶段如果误删了 geometry或保留的几何是null前端遍历时会崩溃。解决在代码里对所有几何加空值保护并在清洗时过滤掉空几何。前端可以这样写const features data.features.filter(f f.geometry f.geometry.coordinates);逻辑说明过滤后 L.geoJSON 接收的 feature 数组一定都带有坐标。如果业务上必须保留空几何要素则需要给前端一个默认形状改成在onEachFeature里判断if (!feature.geometry) return;。5.4 属性中文乱码现象浏览器 Tooltip 显示类似国家的乱码字符。原因GeoJSON 文件不是 UTF-8 编码很多 GIS 工具默认使用 GBK而浏览器 fetch 默认按 UTF-8 解码。解决先把文件用 Python 转成 UTF-8 后再使用with open(raw_gbk.geojson, encodinggbk, errorsignore) as f: content f.read() with open(world_utf8.geojson, w, encodingutf-8) as f: f.write(content)如果需要在前端实时解码上传的文件可以读取arrayBuffer后交给TextDecoder(gbk)。但生产环境我更推荐在构建阶段完成编码转换避免每个用户都承担解码开销。5.5 面积统计结果比常识大了一倍现象脚本输出的国家面积和官方数据差很多有些差到两倍。原因直接用经纬度坐标按平面公式算面积把球面上的多边形当成平面另外某些数据源在导出时已经做了投影拉伸导致面积失真。解决在需要面积指标时使用等积投影。import pyproj from shapely.geometry import shape from shapely.ops import transform feature data[features][0] geom shape(feature[geometry]) project pyproj.Transformer.from_crs(EPSG:4326, ESRI:54009, always_xyTrue).transform projected transform(project, geom) area_m2 projected.area print(f面积: {area_m2 / 1e6:.1f} 平方公里)逻辑说明ESRI:54009是世界摩尔维德等积投影转换后再调用.area才能得到相对可信的球面面积。始终在 WGS84 上直接计算面积就等同于在所有纬度都用同一个尺度高纬度区域的结果一定会偏大。6. 进阶技巧将世界国家 GeoJSON 转成 TopoJSON 并按缩放级别加载6.1 一步压缩成 TopoJSONGeoJSON 的最大冗余在于相邻国家会重复存储同一条边界线。TopoJSON 用弧段索引来共享这些边界体积通常能下降 70%~80%。常见做法是用 JavaScript 生态的命令行工具完成npm install -g topojson-server geo2topo world_simplified.geojson world.topojson ls -lh world.topojson逻辑说明geo2topo会把 GeoJSON 转成 TopoJSON默认把每个 Feature 放在一个对象里。如果你希望按洲合并可以继续用topomergetopomerge continentsworld -k d.properties.continent world.topojson world_merged.topojson参数说明-k指定 merge 的分组键这里按continent属性把各国边界合并成洲界轮廓这会让数据减小更多但会丢失国家边界细节适合低缩放下展示大洲。6.2 前端按缩放级别加载简化等级没有哪种精度能同时满足“秒开”和“放大了还能看清”。我通常生成三个文件低精度、中精度、高精度然后在zoomend事件里切换。let layer null; map.on(zoomend, () { const zoom map.getZoom(); let file world_low.topojson; if (zoom 5 zoom 8) file world_mid.topojson; if (zoom 8) file world_high.topojson; fetch(file) .then((res) res.json()) .then((topo) { const geojson topojson.feature(topo, topo.objects.world); if (layer) map.removeLayer(layer); layer L.geoJSON(geojson).addTo(map); }); });逻辑说明每次缩放结束后先根据 zoom 档选文件再移除旧图层、加入新图层。为了避免请求抖动可以在切换时判断当前已加载的文件名如果每次zoomend都请求低端手机上会有闪烁。topojson.feature方法由topojson-client提供它负责把 TopoJSON 还原为 GeoJSON。6.3 数据上线前的最终验证使用 TopoJSON 后也要做基础校验尤其是坐标范围。这里用一段遍历脚本查找所有数字坐标并计算 bboxpython - PY import json data json.load(open(world.topojson, encodingutf-8)) bbox [180.0, 90.0, -180.0, -90.0] def walk(obj): if isinstance(obj, list): if len(obj) 2 and isinstance(obj[0], (int, float)): yield obj else: for item in obj: yield from walk(item) elif isinstance(obj, dict): for value in obj.values(): yield from walk(value) for coord in walk(data): lon, lat coord[0], coord[1] bbox[0] min(bbox[0], lon) bbox[1] min(bbox[1], lat) bbox[2] max(bbox[2], lon) bbox[3] max(bbox[3], lat) print(bbox:, bbox) assert bbox[0] -180 and bbox[2] 180, 经度越界 assert bbox[1] -90 and bbox[3] 90, 纬度越界 print(坐标范围正确可以上线) PY逻辑说明bbox初值设为经纬度的极值递归遍历 TopoJSON 字典里所有列表把最内层长度为 2 的坐标对当作点更新包围盒。如果越界说明原始数据可能混入了投影坐标或脏值不能上线。这套流程走完后你手里会有一份体积小、加载快、属性统一的世界国家 GeoJSON/TopoJSON 数据包。我早期做地图项目时特别喜欢直接塞高精度原始数据结果每次打开页面都转菊花后面才养成先跑验证脚本、再简化、再压缩的习惯。数据链路里“验证”这个环节最容易被跳过但它恰恰是上线前最后一道后悔药。希望这个方案能帮你少走一圈弯路祝你的地图按时上线。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑