GeoJSON 转 KML / SVG / CSV / PNG:四种格式怎么选、怎么转
前面两篇把坐标系和 GeoJSON 本身讲明白了,这篇聊点落地的:数据到手了,怎么变成别人要的格式。这事儿我在 GeoJSONcn 项目里天天干,用户的诉求五花八门。有人要 KML 丢进 Google Earth,有人要 SVG 进设计稿,有人要 CSV 做数据分析,还有人要一张透明背景的 PNG 大图。
先想清楚:你要的是"画"还是"数"?
选格式得先想清楚一件事:
- 要在地图/地球软件里看 → KML / GeoJSON
- 要进设计工具排版 → SVG
- 要做表格分析/Excel → CSV
- 要一张静态图片 → PNG / JPG
别用错。我见过有人非要把边界导成 CSV 再手动描点,纯属跟自己过不去。
1) GeoJSON → KML(丢进 Google Earth)
KML 是 XML,核心是把坐标从 [lon,lat] 变成 。简化版:
function geojsonToKml(geojson) {
const placemarks = geojson.features.map(f => {
const coords = f.geometry.coordinates[0]
.map(c => `${c[0]},${c[1]},0`).join(' ');
return `<Placemark><name>${f.properties.name || 'unnamed'}</name>
<Polygon><outerBoundaryIs><LinearRing><coordinates>${coords}</coordinates>
</LinearRing></outerBoundaryIs></Polygon></Placemark>`;
}).join('');
return `<?xml version="1.0"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>${placemarks}</Document></kml>`;
}
注意 KML 坐标是 lon,lat,alt 逗号分隔,跟 GeoJSON 的数组不一样。
2) GeoJSON → SVG(进设计稿 / 前端矢量)
SVG 说白了就是一堆 。把多边形坐标拼成 M x y L x y ... Z 即可(注意 SVG 用屏幕坐标,y 轴朝下,要做个简单的经纬度到像素映射):
function project(lon, lat, bounds, w, h) {
const x = (lon - bounds.minLon) / (bounds.maxLon - bounds.minLon) * w;
const y = (bounds.maxLat - lat) / (bounds.maxLat - bounds.minLat) * h;
return [x, y];
}
function geojsonToSvg(geojson, w = 800, h = 600) {
const paths = geojson.features.map(f => {
const d = f.geometry.coordinates[0]
.map((c, i) => (i === 0 ? 'M' : 'L') + project(...c).join(' ')).join(' ') + ' Z';
return `<path d="${d}" fill="#cde" stroke="#369" stroke-width="1"/>`;
}).join('');
return `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}">${paths}</svg>`;
}
3) GeoJSON → CSV(给数据分析)
这个最简单,把每个要素的核心属性摊平:
function geojsonToCsv(geojson) {
const rows = geojson.features.map(f =>
[f.properties.name, f.properties.code, f.geometry.type].join(','));
return 'name,code,geom_type\n' + rows.join('\n');
}
适合做统计、做透视表。但 CSV 不带几何细节,只能存属性,要还原形状得另存坐标。所以它适合属性分析,不适合空间表达。
4) GeoJSON → PNG(透明背景大图)
这个要在 Canvas 上把多边形画出来再 toDataURL。关键点:导出是用数据重画,不是截图 DOM(这点后面讲水印的时候还会提到)。1080p / 2K / 4K 只是改 Canvas 尺寸,逻辑一样:
function drawToCanvas(geojson, size = 1920) {
const cv = document.createElement('canvas');
cv.width = cv.height = size;
const ctx = cv.getContext('2d');
// 先投影到像素,再 fill 每个多边形
geojson.features.forEach(f => ctx.fill());
return cv.toDataURL('image/png');
}
最后用一张表收一下
| 目标 | 选 | 原因 |
|---|---|---|
| Google Earth / 三维地球 | KML | 原生支持 |
| 设计稿 / 矢量排版 | SVG | 无损缩放 |
| Excel / 统计 | CSV | 表格友好 |
| 静态图片 / 印刷 | PNG | 栅格化、可透明 |
我在 GeoJSONcn 上把这四种导出全做了,用户选省市区一键下载,后端就是上面这几段逻辑的强化版(加了精度控制和批量)。
最后
格式转换不难,难的是别选错格式。记住"看地图用 KML、排版用 SVG、分析用 CSV、出图用 PNG",代码都是几十行的活儿。下一篇聊聊前端怎么把这些 GeoJSON 真正画到屏幕上,Canvas、SVG、地图库到底怎么选。