如何在Python的Mapbox中为表示圆半径的LineString添加标注?
问题:在Python的Mapbox地图中为半径线条添加标注
我有一个Python函数,接收坐标后可在Mapbox地图上绘制圆形和线条。我希望给该线条添加标注,用以指示圆的半径(如本示例中的1000m),想询问是否能在Python中实现该功能,现有代码如下:
def func(lat, lon): df = pd.DataFrame( {'lat': [lat], 'lon': [lon]}) gdf = gpd.GeoDataFrame( df, geometry=gpd.points_from_xy(df.lon, df.lat)) fig = px.scatter_mapbox( gdf, lat="lat", lon="lon" ).update_layout(mapbox={"style": "open-street-map"}) gdf_ = gpd.GeoDataFrame( gdf, geometry=gpd.points_from_xy(gdf.lon, gdf.lat)) gdf_.set_crs(epsg=4386, inplace=True) utm = gdf_.estimate_utm_crs() gdf_ = gdf_.to_crs(utm) b = 1000 m = b // 10 p = gdf_.centroid.values[0] arrow = LineString( [p, (p.x + b, p.y), (p.x + b - m, p.y - m), (p.x + b - m, p.y + m), (p.x + b, p.y)] ) def geojson(shape, utm): return gpd.GeoSeries([shape], crs=utm).to_crs("epsg:4386").__geo_interface__ # add circle geometry as layer to mapbox figure fig.update_layout( mapbox={ "layers": [ { "source": geojson(p.buffer(b), utm), "color": "PaleTurquoise", "type": "fill", "opacity": 0.5, }, { "source": geojson(p.buffer(m), utm), "color": "red", "type": "fill", "opacity": 0.5, }, { "source": geojson(arrow, utm), "color": "blue", "type": "line", "opacity": 0.5, "title": 'aaa', }, ] } ) return fig
回答
完全可以实现,Plotly的Mapbox支持两种方式添加半径标注:直接添加文本注解,或者通过地图图层添加文本符号。下面是修改后的代码,实现了在半径线条中间添加"1000m"的标注:
import pandas as pd import geopandas as gpd import plotly.express as px from shapely.geometry import LineString, Point def func(lat, lon): df = pd.DataFrame( {'lat': [lat], 'lon': [lon]}) gdf = gpd.GeoDataFrame( df, geometry=gpd.points_from_xy(df.lon, df.lat)) fig = px.scatter_mapbox( gdf, lat="lat", lon="lon" ).update_layout(mapbox={"style": "open-street-map"}) gdf_ = gpd.GeoDataFrame( gdf, geometry=gpd.points_from_xy(gdf.lon, gdf.lat)) gdf_.set_crs(epsg=4386, inplace=True) utm = gdf_.estimate_utm_crs() gdf_ = gdf_.to_crs(utm) b = 1000 # 半径长度 m = b // 10 p = gdf_.centroid.values[0] arrow = LineString( [p, (p.x + b, p.y), (p.x + b - m, p.y - m), (p.x + b - m, p.y + m), (p.x + b, p.y)] ) # 定义转换GeoJSON的函数 def geojson(shape, utm): return gpd.GeoSeries([shape], crs=utm).to_crs("epsg:4386").__geo_interface__ # 添加圆形和箭头图层 fig.update_layout( mapbox={ "layers": [ { "source": geojson(p.buffer(b), utm), "color": "PaleTurquoise", "type": "fill", "opacity": 0.5, }, { "source": geojson(p.buffer(m), utm), "color": "red", "type": "fill", "opacity": 0.5, }, { "source": geojson(arrow, utm), "color": "blue", "type": "line", "opacity": 0.5, }, ] } ) # 计算标注位置:在半径线条的中点 label_point_utm = Point(p.x + b/2, p.y) # 转换为WGS84坐标系(经纬度) label_point_wgs84 = gpd.GeoSeries([label_point_utm], crs=utm).to_crs("epsg:4386").iloc[0] label_lon, label_lat = label_point_wgs84.x, label_point_wgs84.y # 添加文本标注 fig.add_annotation( x=label_lon, y=label_lat, text=f"{b}m", showarrow=False, font=dict( size=12, color="black" ), bgcolor="white", opacity=0.8 ) return fig # 测试调用 # fig = func(39.9042, 116.4074) # fig.show()
关键说明:
- 标注位置计算:在UTM坐标系下计算半径线条的中点,再转换回WGS84经纬度,确保标注位置准确对应地图上的线条位置。
- 文本注解添加:使用
fig.add_annotation()直接添加文本,可自定义字体、背景色、透明度等样式,showarrow=False隐藏箭头,只显示文本。 - 可选方式:如果需要批量添加标注或更灵活的样式,也可以用Mapbox的
symbol类型图层,将标注点作为GeoJSON源,在图层的layout中设置text字段。
内容的提问来源于stack exchange,提问作者test tes
相关产品推荐
相关产品推荐

