做了一个小工具,叫 MapPoster Online,可以在浏览器里把城市地图生成装饰画/海报。
在线体验: https://maptoposter.0v0.one
GitHub: https://github.com/ianho7/maptoposter-online
这个项目的来源比较简单:之前看到过一个 Python CLI 项目 maptoposter,可以生成城市地图海报,效果挺有意思。但 CLI 对非 Python 用户来说还是有一点点门槛,需要装环境、跑命令、找输出文件。
所以我做了一个网页版,目标是 0 门槛、打开网页后就能选城市、调样式、导出图片。
现在能做什么
- 选择城市并生成地图海报
- 调整地图半径、主题、颜色、字体和版式
- 支持 A4 竖版、A4 横版、方形、手机壁纸、桌面 16:9 等尺寸
- 支持 300 DPI 导出,主要是为了打印
- 内置 20 种主题
- 可以上传 TTF/OTF 字体
- 支持英文、中文、日文、韩文、德文、西班牙文、法文界面
- 已获取的地图数据会缓存在浏览器 IndexedDB 里,重复生成会快一些
一些生成效果:


技术上主要做了什么
前端是 React 19 + TypeScript + Vite + Tailwind CSS 。渲染部分用了 Rust/WASM ,底层是 tiny-skia 。
地图数据默认主要来自 OpenStreetMap ,通过 Overpass API 获取道路、水体、公园和 POI 数据。
比较麻烦的地方是数据量。比如东京 18km 半径的测试数据,道路要素可以到 56 万以上,原始 GeoJSON 大约 40MB 。直接在浏览器里处理这种 GeoJSON ,很容易被 JSON.parse、对象转换、JS 和 WASM 之间的数据传输拖慢。
后面做了几类优化:
- 把复杂 GeoJSON 压平成
Float64Array,减少嵌套对象转换 - 用 Worker 处理数据获取和投影转换,避免主线程卡死
- 大块道路数据按道路边界切成多个 shard ,并行处理
- WASM 渲染时尽量单次扫描,把道路按类型分发到不同
PathBuilder - Overpass 查询面积过大时做分块,并发检查多个公共镜像节点
- 使用 IndexedDB 缓存获取过的数据
因为地图数据量上来以后,普通 JSON 对象流转的成本会非常明显。
目前的不足
先说几个已知问题,免得大家试用时踩坑:
- 第一次获取数据,特别是大城市、大半径生成还是可能慢,尤其受 Overpass 节点状态影响,哪怕已经做了多节点的竞速机制和分批获取数据(毕竟是公益节点,而且数据量特别大)
- 不同城市的 OSM 数据完整度不一样,有些地方水域、绿地或 POI 效果会受影响。
想听听大家的反馈
主要想问几个问题:
- 默认主题是否够用?本地开发是做了一个直接从剪贴板获取 JSON 的,因为我定义了一套 prompt 让 AI 帮我根据上传的图片生成配色,还挺实用,但是感觉解释成本有点高,所以暂时在线上版本隐藏起来了
- 如果作为地图海报工具,大家更希望加哪些控制项?比如控制是否渲染 POI 、道路等级、水域样式等。
- 在浏览器端处理 OSM / Overpass 数据,还有没有更稳的实践?
在线体验: https://maptoposter.0v0.one
GitHub: https://github.com/ianho7/maptoposter-online
欢迎直接回复,也可以在 GitHub 开 issue ,当然如果能给我一个 Star 就更好了 😊