Python使用folium制作地图并生成png图片
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
第一章 使用folium制作地图
第二章 使用Html2Image生成png图片
第三章 使用reportlab制作pdf报告
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- Python使用folium制作地图并生成png图片
- 前言
- 一、folium是什么?
- 二、使用步骤
- 1.安装和导入库
- 2.创建地图或图层
- 3.添加覆盖物
- 4.地图参数
- 5.生成html
- 6.其他
- 总结
前言
提示:这里可以添加本文要记录的大概内容:
我讲一下我这个需求的来源,做的项目是一个地理空间查询和使用的系统,通过在前端调用高德地图api创建了一个查询区域,获取区域内的地理数据。具体的需求就是,将查询区域和地理数据制作成一个覆盖率分析报告,报告中的其他内容都已经完成,但是报告中需要展示高德地图、查询区域、地理数据的完整图片这个功能卡了2个星期,主要原因是我对地理空间数据不熟悉,很多python相关库也不清楚,在构建图形的过程中走了很多弯路。
现在将整个实现过程梳理完成,希望对各位同道有帮助,跟其他文章和官网不同,本博客是以使用的优先级来讲解这个库。<我们靠所得来谋生,但靠给予来创造生活>
提示:以下是本篇文章正文内容,下面案例可供参考
一、folium是什么?
folium是js上著名的地理信息可视化库leafet.js为Python提供的接口,通过它,我们可以通过在Python端编写代码操纵数据,来调用leaflet的相关功能,基于内建的osm或自行获取的osm资源和地图原件进行地理信息内容的可视化,以及制作优美的可交互地图,是通过不断添加图层元素来定义一个Map对象,最后以几种方式将Map对象展现出来。
而在Map对象的生成形式上,可以在定义所有的图层内容之后,将其保存为html文件在浏览器中独立显示,也可以基于jupyter notebook在一个ipynb文件嵌入对应的交互地图。
二、使用步骤
1.安装和导入库
官网链接:https://pypi.org/project/folium/
pip install folium
代码如下(示例):
import folium
2.创建地图或图层
如何对地图没有要求,可以直接创建地图,但是对地图有要求,可以通过设置参数或加载图层来实现。
def map2png(map_data,out_file='pdf.png'):
# 1.直接构造,默认底图
mo = folium.Map(location=[45.5236, -122.6750])
# 2.替换成高德底图
mo = folium.Map(location=location, # [39.917834, 116.397036]
zoom_start=zoom_start, # 13
tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}')
# 3.添加图层
mo = folium.Map(location=location, # [39.917834, 116.397036]
zoom_start=zoom_start, # 13
tiles=None)
folium.TileLayer(
tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
attr="© <a href=http://ditu.amap.com/>高德地图</a>",
min_zoom=0,
max_zoom=19,
control=True,
show=True).add_to(mo)
mo.save('test.html')
3.添加覆盖物
覆盖物就是地理空间常用的数据,包括点线面等,数据有多种来源,可以是数据库读出来、文件读出来的、或者网络传输geojson等。
import folium
def map2png(map_data,out_file='pdf.png'):
# 1.直接构造,默认底图
mo = folium.Map(location=[45.5236, -122.6750])
# 添加一个点
folium.Marker(
location=[45.3311, -121.7113],
popup="Timberline Lodge",
icon=folium.Icon(color="green"),).add_to(m)
# 添加一个线形
folium.PolyLine(
location=[[38.68,115.67],
[38.85,115.48],
[38.65,115.37],
[38.68,115.67]],
popup="Timberline Lodge",
icon=folium.Icon(color="green"),).add_to(m)
# 添加一个面
folium.Polygon(
locations=[[38.68,115.67],
[38.85,115.48],
[38.65,115.37],
[38.68,115.67]],
color='green',
fill=True, weight=2).add_to(mo)
mo.save('test.html')
4.地图参数
我为什要在画完地图和覆盖物之后才说参数?我不可能坑同学。
folium的Map参数有很多,常用的比如location和zoom_start。很多时候都是创建地图的时候就带着(这不是很正确)。创建地图的的时候,我们很多时候是不知道地图的中心点和缩放级别的,这样就很麻烦,还要肉眼去看,一次次的调整。
Map有一个方法fit_bounds,可以实现根据图形内容自动调整中心点和缩放级别,fit_bounds方法的参数跟点线面的参数时一样的。使用fit_bounds的时候尽量不要设置location参数,使用[0,0]值。
import folium
def map2png(map_data,out_file='pdf.png'):
# 1.直接构造,默认底图
mo = folium.Map(location=[0, 0])
# 添加一个点
folium.Marker(
location=[45.3311, -121.7113],
popup="Timberline Lodge",
icon=folium.Icon(color="green"),).add_to(m)
# 添加一个线形
folium.PolyLine(
location=[[38.68,115.67],
[38.85,115.48],
[38.65,115.37],
[38.68,115.67]],
popup="Timberline Lodge",
icon=folium.Icon(color="green"),).add_to(m)
# 添加一个面
folium.Polygon(
locations=[[38.68,115.67],
[38.85,115.48],
[38.65,115.37],
[38.68,115.67]],
color='green',
fill=True, weight=2).add_to(mo)
mo.fit_bounds([[38.68,115.67],
[38.85,115.48],
[38.65,115.37],
[38.68,115.67]]) # 根据范围缩放地图
mo.save('test.html')
其他参数和方法我这里列举出来,供同学们参考。
folium.Map(
location=None, # 中心点
width='100%', # 基于浏览器左上角的屏幕宽的比例
height='100%', # 基于浏览器左上角的屏幕高德比例
left='0%', # 基于浏览器左侧占比
top='0%', # 基于浏览器顶部占比
position='relative', # 地图位置
tiles='OpenStreetMap', # 多个str参数(map自己的),也可以是瓦片
attr=None, # 设置瓦片时,需要传值
min_zoom=0, # 最小缩放级别
max_zoom=18, # 最大缩放级别 30
zoom_start=10, # 开始缩放级别
min_lat=-90,
max_lat=90,
min_lon=-180,
max_lon=180,
max_bounds=False,
crs='EPSG3857', # 定义投影地理点的坐标参考系
control_scale=False,
prefer_canvas=False,
no_touch=False, # 是否禁止手动操作,默认为False
disable_3d=False, # 加速CSS 3D加载
png_enabled=False, # map是否可以生成图片,设置为true后可以使用map._to_png(),不建议使用,需要服务器安装浏览器包而且他的方法过时了。
zoom_control=True, # 地图上显示缩放控件,默认为True
**kwargs}
)
5.生成html
map.save()函数会生成一个html网页,默认保存在py的同一级目录下,因为我们项目的需求,保存成html在读出来生成png,这个读写过程有点浪费,所以我这里获取到html的页面内容,不调用save方法,直接将html的内容创给html2image生成图片。
import folium
def map2png(map_data,out_file='pdf.png'):
# 1.直接构造,默认底图
mo = folium.Map(location=[0, 0])
# 添加一个点
folium.Marker(
location=[45.3311, -121.7113],
popup="Timberline Lodge",
icon=folium.Icon(color="green"),).add_to(m)
# 添加一个线形
folium.PolyLine(
location=[[38.68,115.67],
[38.85,115.48],
[38.65,115.37],
[38.68,115.67]],
popup="Timberline Lodge",
icon=folium.Icon(color="green"),).add_to(m)
# 添加一个面
folium.Polygon(
locations=[[38.68,115.67],
[38.85,115.48],
[38.65,115.37],
[38.68,115.67]],
color='green',
fill=True, weight=2).add_to(mo)
mo.fit_bounds([[38.68,115.67],
[38.85,115.48],
[38.65,115.37],
[38.68,115.67]]) # 根据范围缩放地图
root = mo.get_root()
html = root.render() # 这个拿到的就是一个html的内容
# mo.save('text.html')
6.其他
本博客开始我就介绍了,folium是js上著名的地理信息可视化库leafet.js为Python提供的接口,我们看下就提都调用了那些接口,主要是些js+css。因为中所周知的原因,国内访问国外的接口会存在限制,这些借口在未来可能成为程序的漏洞(有些无法加载,这里不考虑图层瓦片,至少可以用国内图层对吧)。# noqa标记的就是告诉程序可能出错的,忽略警告。
_default_js = [
('leaflet',
'https://cdn.jsdelivr.net/npm/leaflet@1.6.0/dist/leaflet.js'),
('jquery',
'https://code.jquery.com/jquery-1.12.4.min.js'),
('bootstrap',
'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js'),
('awesome_markers',
'https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js'), # noqa
]
_default_css = [
('leaflet_css',
'https://cdn.jsdelivr.net/npm/leaflet@1.6.0/dist/leaflet.css'),
('bootstrap_css',
'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'),
('bootstrap_theme_css',
'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css'), # noqa
('awesome_markers_font_css',
'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css'), # noqa
('awesome_markers_css',
'https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css'), # noqa
('awesome_rotate_css',
'https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css'), # noqa
]
针对可能出现的加载问题,建议将这些库文件放在本地,替换html中的链接。
此处可参考https://blog.csdn.net/weixin_42148809/article/details/120969710
。
总结
提示:这里对文章进行总结:
本博客是以使用的优先级来讲解这个库。<我们靠所得来谋生,但靠给予来创造生活>