Plotly mapbox:获取当前视图/缩放级别的几何图形

Plotly mapbox : Get the geometry of current view / zoom level

我正在 Flask / Dash 应用程序中使用 plotly 渲染 scattermapbox。我设置了默认的 zoom 级别和 lat,long 坐标。当用户通过 plotly 界面平移地图并更改缩放级别时,我想用点和数据层更新地图。

这里有一些代码供参考:

import pandas as pd
import geopandas as gpd

# import mapbox
import requests
import plotly.graph_objects as go

# Update with host url
df_geo = gpd.GeoDataFrame.from_features(
    requests.get(
        "https://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_050_00_20m.json"
    ).json()
)

import plotly.graph_objects as go

fig = go.Figure(
    go.Choroplethmapbox(
        geojson=df_geo.set_index("GEO_ID")["geometry"].__geo_interface__,
        locations=df_geo["GEO_ID"],
        z=df_geo["CENSUSAREA"],
        autocolorscale=False,
        colorscale="Viridis",
        zmin=df_geo["CENSUSAREA"].min(),
        zmax=df_geo["CENSUSAREA"].quantile(0.95),
        marker_line_width=0,
        colorbar={"orientation": "h", "x": 0.5, "yanchor": "middle", "y": 0.1},
    )
)


fig.update_layout(
    mapbox_style="carto-positron",
    # mapbox_accesstoken=token,
    mapbox_zoom=3,
    mapbox_center={"lat": 37.0902, "lon": -95.7129},
    margin={"r": 0, "t": 0, "l": 0, "b": 0},
)

fig.show()

我的问题是,如何获取当前地图视图的geometries / bboxlat,longs coords

文档链接以供参考:

https://plotly.com/python/reference/#scattermapbox

https://dash.plotly.com/dash-core-components/graph

    mapbox 上的
  • relayoutData return centercoordinates
  • 已通过使用客户端回调将此插入到跟踪中进行了演示。这是可行的,但是为了提高效率,我真的只想更新图形而不是 re-render 它。
import pandas as pd
import geopandas as gpd
import requests
import plotly.graph_objects as go
from jupyter_dash import JupyterDash
import dash
from dash.dependencies import Input, Output, State
import json

# Update with host url
df_geo = gpd.GeoDataFrame.from_features(
    requests.get(
        "https://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_050_00_20m.json"
    ).json()
)

fig = go.Figure(
    [
        go.Choroplethmapbox(
            geojson=df_geo.set_index("GEO_ID")["geometry"].__geo_interface__,
            locations=df_geo["GEO_ID"],
            z=df_geo["CENSUSAREA"],
            autocolorscale=False,
            colorscale="Viridis",
            zmin=df_geo["CENSUSAREA"].min(),
            zmax=df_geo["CENSUSAREA"].quantile(0.95),
            marker_line_width=0,
            name="choropleth"
            # colorbar={"orientation": "h", "x": 0.5, "yanchor": "middle", "y": 0.1},
        ),
        go.Scattermapbox(
            name="scatter", marker={"size": 30, "color": "red", "opacity": 1}
        ),
    ]
)

fig.update_layout(
    mapbox_style="carto-positron",
    # mapbox_accesstoken=token,
    mapbox_zoom=3,
    mapbox_center={"lat": 37.0902, "lon": -95.7129},
    margin={"r": 0, "t": 0, "l": 0, "b": 0},
    datarevision=0,
    height=300,
    width=600,
    autosize=False,
)

# Build App
app = JupyterDash(__name__)
app.layout = dash.html.Div(
    [
        dash.dcc.Checklist(
            options=[{"label":"refesh", "value":"yes"}],
            id="refresh",
        ),
        dash.dcc.Graph(id="mapbox_fig", figure=fig),
        dash.html.Div(
            id="debug_container",
        ),
        dash.dcc.Store(
            id="points-store",
            data={
                "lat": [],
                "lon": [],
            },
        ),
    ]
)


@app.callback(
    Output("points-store", "data"),
    Output("debug_container", "children"),
    Input("mapbox_fig", "relayoutData"),
    Input("refresh","value")
)
def mapbox_cb(mapbox_cfg, refresh):
    try:
        refresh = refresh[0]=="yes"
    except Exception:
        refresh = False
    if mapbox_cfg and "mapbox.zoom" in mapbox_cfg.keys() and refresh:
        bbox = np.array(mapbox_cfg["mapbox._derived"]["coordinates"])
        # bbox = bbox * .8
        data = {
            "lon": bbox[:, 0].tolist() + [mapbox_cfg["mapbox.center"]["lon"]],
            "lat": bbox[:, 1].tolist() + [mapbox_cfg["mapbox.center"]["lat"]],
        }

        return data, [
            dash.html.Pre(json.dumps(mapbox_cfg, indent=2)),
            dash.html.Pre(json.dumps(data, indent=2)),
        ]
    else:
        raise dash.exceptions.PreventUpdate


app.clientside_callback(
    """
    function(data, fig) {
        fig.data[1]['lat'] = data['lat'];
        fig.data[1]['lon'] = data['lon'];
        fig.layout.datarevision = fig.layout.datarevision + 1;
        /* return fig; */
        return JSON.parse(JSON.stringify(fig)); 
    }
    """,
    Output("mapbox_fig", "figure"),
    Input("points-store", "data"),
    State("mapbox_fig", "figure"),
)

app.run_server(mode="inline")