Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update Folium map without re rendering entire map?

I have a Folium map placed in PySide6 QWebEngineView. Map coordinates are updated each second and the map is recentered to the new position. However, this is re-rendering entire map with each update and it causes "flashing", which is not user friendly.

I need to make the map to reposition by smooth dragging/sliding, or even jump will be fine if flashing does not happen. I could not find any real solution for it anywhere.

This is the code I have in map.py:

import io
import sys
import folium
from PySide6.QtCore import QTimer
from PySide6.QtWebEngineWidgets import QWebEngineView
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget


class MapWebView(QWebEngineView):
    def __init__(self, initial_coordinates: tuple[float, float]):
        super().__init__()
        self.folium_map = folium.Map(
            location=initial_coordinates,
            zoom_start=13,
            zoom_control=False,
            attribution_control=False
        )
        self.data = io.BytesIO()
        self.folium_map.save(self.data, close_file=False)
        self.setHtml(self.data.getvalue().decode())

    def update_map(self, new_coords: tuple[float, float]):
        self.folium_map = folium.Map(
            location=new_coords,
            zoom_start=13,
            zoom_control=False,
            attribution_control=False
        )
        self.data = io.BytesIO()
        self.folium_map.save(self.data, close_file=False)
        self.setHtml(self.data.getvalue().decode())


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(600, 600)
        self.setCentralWidget(QWidget())
        self.centralWidget().setLayout(QVBoxLayout())

        self.map_webview = MapWebView((47.030780, 8.656176))
        self.centralWidget().layout().addWidget(self.map_webview)

        timer = QTimer(self)
        timer.timeout.connect(self.update_map)
        timer.start(1000)

    def update_map(self):
        current_coords = self.map_webview.folium_map.location
        new_coords = (current_coords[0] + 0.002, current_coords[1] + 0.002)
        self.map_webview.update_map(new_coords)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
like image 227
Irakli Skhirtladze Avatar asked Dec 16 '25 21:12

Irakli Skhirtladze


1 Answers

I discovered you can run JavaScript code to update data in html without rendering it again.

You have to get layer name self.folium_map.get_name() and create JavaScript code with function layer_name.setView(coords) and run it with self.page().runJavaScript(js_code)

It needs also to assign new coords to self.folium_map.location in Python because JavaScript doesn't update this value and you need it in next calculations.

def update_map(self, new_coords: tuple[float, float]):
    self.folium_map.location = new_coords  # keep it for next calculation because JavaScript doesn't update it 
    
    map_name = self.folium_map.get_name()

    js_code = f'{map_name}.setView({list(new_coords)})'  # I use `list()` because JavaScript needs `[ ]` instead of `( )`
    #print(js_code)

    self.page().runJavaScript(js_code)

Other examples:

Set lat, long and zoom

js_code = f'{map_name}.setView({list(new_coords)}, 13)'  # lat, lng and zoom
    
js_code = f'{map_name}.setView({{lat: {new_coords[0]}, lng: {new_coords[1]} }}, 13)'  # lat, lng and zoom

Set zoom

js_code = f'{map_name}.setZoom(8)'

Display popup window with current values.

js_code = f'alert("Center: " + {map_name}.getCenter() + " Zoom: " + {map_name}.getZoom())

Some places where I found some information:

python - QWebEngineView - Javascript Callback - Stack Overflow

javascript - Retaining zoom and map center in Shiny for Python with Folium when changing map layer - Stack Overflow

Updating folium coordinates on callback in dash app - Dash Python - Plotly Community Forum

like image 176
furas Avatar answered Dec 19 '25 11:12

furas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!