Plotly散点地图实时更新——标记符号不变

前端开发 2026-07-09

使用Plotly,我想在地图上实时显示一系列符号。

请看下面的情形:

import threading, datetime, dash, time
from dash import dcc, html, dash_table, Patch
from dash.dependencies import Input, Output, State
from plotly.subplots import make_subplots
import plotly.express as px
import plotly.graph_objs as go


class PlotlyApp(threading.Thread):
    def __init__(self):
        super().__init__(name='PlotlyApp')
        self.toggle = False
        self.toggle_time = datetime.datetime.now(datetime.timezone.utc)
        self.loc_x, self.loc_y = 50, -50

    def run(self):
        app = dash.Dash(__name__)

        self.fig = go.Figure()
        self.fig.add_scattermap(lat=[self.loc_x], lon=[self.loc_y])
        self.fig.add_scattermap()
        self.fig.update_layout(
            uirevision=True,
            map_style="open-street-map", 
            map_zoom=18, 
            map_center_lat = self.loc_x, 
            map_center_lon=self.loc_y, 
            margin={"r": 5, "t": 0, "l": 5, "b": 0},
        )
        app.layout = html.Div([
            dcc.Graph(
                id='graph', 
                figure=self.fig, 
                style={"height": '85vh'}, 
                animate=True,
                # config={'responsive':True}
            ),
            dcc.Interval(
                id='interval',
                interval=1000,  # update every 1 second
                disabled=False
            ),
            # style={"height": '100vh'}
        ]),

        @app.callback(
            Output('graph', 'figure'),
            [Input('interval', 'n_intervals')],
            # prevent_initial_call=True,
        )
        def _graph(*args):
            now = datetime.datetime.now(datetime.timezone.utc)
            changes_x, changes_y = [], []
            if now > (self.toggle_time + datetime.timedelta(seconds=10)):
                self.toggle = not self.toggle
                self.toggle_time = now
                print('toggle {}'.format(self.toggle))
            if self.toggle:
                x1 = self.loc_x - 0.0001
                x2 = self.loc_x + 0.0001
                y1 = self.loc_y - 0.0001
                y2 = self.loc_y + 0.0001
                changes_x.extend([
                    x1,
                    x2,
                    x1,
                    x2
                ])
                changes_y.extend([
                    y1,
                    y2,
                    y2,
                    y1
                ])

            with self.fig.batch_update():
                self.fig.data[1].lat = changes_x
                self.fig.data[1].lon = changes_y
            self.fig.update_annotations(overwrite=True)
            self.fig.update_geos(overwrite=True)
            self.fig.update_layout(overwrite=True)
            self.fig.update_layout_images(overwrite=True)
            self.fig.update_mapboxes(overwrite=True)
            self.fig.update_maps(overwrite=True)
            self.fig.update_shapes(overwrite=True)
            self.fig.update_traces(overwrite=True)
            self.dt_update = now
            return self.fig
        app.run(debug=True, use_reloader=False, dev_tools_ui=True)

if __name__ == "__main__":
    pa = PlotlyApp()
    pa.run()
    while True:
        time.sleep(1)

运行该应用显示它在本地主机上运行;在地址处打开后,可以看到地图中央有一个蓝点。

正如脚本所示,每十秒钟会在蓝点周围新增一组点,然后将其移除(同时也会打印出一个“toggle true/false”的信息)。然而,这并没有在视觉上显示出来。

如果在没有周围对象时刷新网页,那么屏幕上只有蓝点可见,永远不会出现其他内容。如果在周围点存在时刷新网页,则会看到蓝点周围出现一组红点……但它们永远不会消失(即使底层数据消失)。

有趣的是,如果将鼠标移到红点上,当存在数据时会有悬停文本显示;而当底层数据被清空时,悬停文本就不再显示。不过红点本身不受影响。

有人知道这是为什么,以及如何实现期望的行为吗?

解决方案

在Plotly社区论坛上找到了一个答案(https://community.plotly.com/t/update-dcc-graph-scattermapbox-on-interval/27744/6):如果我在 dcc.Graph 构造器中移除 animate=True 参数,问题就能解决——周围的点会按预期出现和消失。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章