You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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()

关键说明:

  1. 标注位置计算:在UTM坐标系下计算半径线条的中点,再转换回WGS84经纬度,确保标注位置准确对应地图上的线条位置。
  2. 文本注解添加:使用fig.add_annotation()直接添加文本,可自定义字体、背景色、透明度等样式,showarrow=False隐藏箭头,只显示文本。
  3. 可选方式:如果需要批量添加标注或更灵活的样式,也可以用Mapbox的symbol类型图层,将标注点作为GeoJSON源,在图层的layout中设置text字段。

内容的提问来源于stack exchange,提问作者test tes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 22:25:25