普通在线地图更关心道路导航、地点搜索和路线规划,但如果需求变成“把一座城市的街道、建筑、水域和绿地绘制成一张具有设计感的图片”,传统地图服务往往不是最方便的工具。
Prettymaps解决的就是这一类问题。它并不是一个导航软件,而是一个Python地图绘制库:从OpenStreetMap获取地理数据,再借助OSMnx、Matplotlib、Shapely和vsketch等工具,将道路、建筑、水域、绿地等对象转换成可以自由调整样式的地图图形。
从项目目前的定位来看,它更接近“地图数据获取 + Python绘图 + 生成艺术”之间的一层封装。用户不必从头处理完整的OpenStreetMap数据流程,就可以通过相对简洁的代码生成一个地点的风格化地图。

Prettymaps主要解决什么问题
如果直接使用OpenStreetMap原始数据制作地图,通常需要处理地点查询、道路网络、建筑轮廓、空间范围、坐标投影以及Matplotlib绘图等多个环节。对于只是想制作一张视觉化地图的用户,这些步骤容易让代码迅速变得复杂。
Prettymaps把其中不少流程集中到了prettymaps.plot()接口中。最简单的情况下,只需要提供一个地点:
import prettymaps plot = prettymaps.plot( 'Stad van de Zon, Heerhugowaard, Netherlands' )
项目教程显示,查询位置不仅可以使用地址或地名,还可以直接传入经纬度坐标,也可以提供GeoDataFrame形式的自定义边界。
这意味着它既适合快速绘制某个街区,也可以用于已经掌握GIS数据、希望进一步控制地图范围的Python用户。
地图数据和绘图是怎样组合的
Prettymaps生成的地图并不是简单截取一个在线地图页面。它会根据配置获取OpenStreetMap中的不同地理对象,然后分别进行绘制。
例如一张城市地图可能包含:
道路和不同等级的街道;
建筑物轮廓;
公园、草地和森林;
河流、湖泊、海湾等水域;
停车场、步行区域或码头;
地图边界和背景。
这些对象可以被拆分成不同图层,再分别设置颜色、边框、线宽、透明度以及其他Matplotlib样式参数。因此,同一个地点并不只能生成一种固定地图。
这也是Prettymaps和普通“地图截图工具”的主要差别:地图中的建筑、道路和自然区域仍然是可以通过代码分别控制的地理数据,而不是一张已经完全扁平化的底图。
图层和样式是核心控制方式
项目当前教程中比较重要的两个参数是layers和style。
layers决定从OpenStreetMap中获取哪些对象。例如,可以根据OpenStreetMap标签查询建筑、水域、森林和公园:
layers={
"green": {
"tags": {
"landuse": "grass",
"natural": ["island", "wood"],
"leisure": "park"
}
},
"water": {
"tags": {
"natural": ["water", "bay"]
}
},
"building": {
"tags": {
"building": True
}
}
}style则负责决定这些图层最终怎样显示。用户可以为不同对象定义填充颜色、轮廓颜色、线宽和调色板。
例如建筑和水域完全可以使用不同的视觉语言,建筑甚至可以从一组颜色中选择调色板,而不是所有建筑使用同一种颜色。
对于需要制作海报、城市插画、项目封面或地理主题视觉素材的用户,这种“先选择地图对象,再控制视觉样式”的方式要比修改一张地图截图灵活得多。
不想从零配色可以使用预设
并不是所有人都希望每次生成地图时重新配置道路宽度、建筑颜色和背景。Prettymaps因此提供了Preset预设机制。
调用时可以直接指定预设:
plot = prettymaps.plot( 'Stad van de Zon, Heerhugowaard, Netherlands', preset='minimal' )
项目当前文档还列出了default、minimal、macao、tijuca等预设示例。通过prettymaps.presets()可以查看可用预设,通过prettymaps.preset()可以检查具体配置。
如果已经形成自己的地图视觉方案,还可以使用prettymaps.create_preset()创建预设,将图层和样式配置保存下来。
对于需要重复制作不同城市地图的场景,这一点尤其有价值。比如一套文章封面需要分别绘制北京、东京和巴黎,与其分别调整三套颜色,不如先确定统一的视觉规范,再让不同地点复用同一套预设。
生成结果还能继续用Matplotlib处理
prettymaps.plot()返回的并不只是最终图片。当前项目将结果封装为一个Plot数据类,其中包含各图层的GeoDataFrame,以及Matplotlib的fig和ax对象。
因此,地图生成以后仍然可以继续进行Matplotlib级别的修改。例如增加标题:
plot.fig.patch.set_facecolor('#F2F4CB')
plot.ax.set_title('Barcelona', font='serif', size=50)用户也可以直接访问某一个图层对应的GeoDataFrame,继续筛选建筑、检查几何对象,或者把这些数据用于其他空间分析和绘图流程。
从这个角度看,Prettymaps更像一个可继续扩展的Python绘图流程,而不是点击“生成”之后就无法再修改的成品地图工具。
除了普通地图还能做哪些效果
项目当前教程已经覆盖了一些比基础街区地图更进一步的用法。
绘制完整行政或地理区域
默认绘图通常围绕指定地点和一定半径展开。如果希望按照实际区域边界进行绘制,可以将radius设置为False。
plot = prettymaps.plot( 'Bom Fim, Porto Alegre, Brasil', radius=False )
在同一画布组合多个地区
项目提供prettymaps.multiplot和prettymaps.Subplot,可以把多个区域放到同一张画布中,并为不同区域指定不同样式。
这种方式可以用于城市街区对比、多地点主题海报,或者将几个相关区域组合成一张视觉作品。
加入地形阴影
当前版本支持hillshade地形阴影。对于山地、海岛或地形变化明显的地区,可以将高低起伏产生的阴影加入地图,让单纯的道路和建筑图层获得更多地形信息。
标记关键地点
Prettymaps还支持keypoints。项目示例中既可以按照OpenStreetMap标签寻找海滩等对象,也可以搜索指定名称的地点。
如果制作的是旅游区域、自然地理主题或者特定地点的地图,这种方式比单纯展示道路更加实用。
还可以为绘图机输出SVG
Prettymaps集成了vsketch相关能力,并提供plotter模式。官方教程给出的用途是生成适合pen plotter绘图机使用的SVG。
plot = prettymaps.plot(
(41.39491, 2.17557),
mode='plotter',
layers=dict(perimeter={}),
preset='barcelona-plotter',
scale_x=0.6,
scale_y=-0.6
)这使它的用途不仅停留在网页图片或数据可视化,还可以延伸到实体绘图、地图艺术和生成艺术作品。
如果用户只是需要一张标准导航地图,这些能力可能没有太大价值;如果目标本身就是地图视觉设计,输出方式的可控性才是Prettymaps真正值得关注的部分。
安装和运行需要哪些环境
项目官方提供的本地安装方式比较直接:
pip install prettymaps
也可以在Google Colab中从GitHub仓库安装。官方说明中,Colab安装完成后需要重启Runtime再导入Prettymaps。
仓库当前还包含一个Streamlit前端,安装项目后可以从仓库目录启动:
streamlit run app.py
这为不希望每一次都直接操作Python函数的用户提供了另一种交互方式,不过Prettymaps整体仍然是一个Python开发工具,并不是完全免配置的桌面地图软件。
需要注意的是,当前主分支的setup.py声明Python版本要求为3.12及以上,而PyPI上已经发布的1.4.2版本元数据显示Python要求为3.11及以上。使用GitHub主分支和使用PyPI稳定包时,环境要求可能并不完全一致,安装前最好根据实际使用的版本检查依赖。
poxiaoxi博客
精彩评论