Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Updating TileLayer via callback with non-integer zoom generates failing tiles requests #236

Open
Farkites opened this issue Jun 4, 2024 · 0 comments

Comments

@Farkites
Copy link

Farkites commented Jun 4, 2024

Description

When the zoom value is not an integer and the dl.TileLayer is updated via callback the initial tiles requests are wrong and therefore failing. The URL for these requests is using the zoom value instead of it corresponding zoom level, which should be the closest integer.

For example, if the zoom is set to 17.5 and the children prop is updated via callback to a different dl.TileLayer the first requests would be https://b.tile.openstreetmap.org/17.5/52778/63857.png (which is shows an invalid tile error) when it should instead be https://b.tile.openstreetmap.org/18/52778/63857.png

After these failed requests if the zoom value changes it then generates the correct URLs for the tiles requests.

Reproduce the bug running the code below:

import dash
from dash import html, dcc, callback, Input, Output
import dash_leaflet as dl

CARTO_TILES = dl.TileLayer(
    url="https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png",
    maxZoom=18,
    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
)


def serve_layout():
    return html.Div(
        children=[
            "Tiles dropdown",
            dcc.Dropdown(
                id="tiles_dropdown",
                options=[{"label": x, "value": x} for x in ["OSM", "CARTO"]],
                value="CARTO",
            ),
            dl.Map(
                [CARTO_TILES],
                center=[45.519, -73.576],
                zoom=17.5,
                zoomSnap=0,
                style={"width": "100%", "height": "400px"},
                id="leaflet",
            ),
        ],
    )


app = dash.Dash(__name__)
server = app.server
app.layout = serve_layout


@callback(
    Output("leaflet", "children"),
    Input("tiles_dropdown", "value"),
    prevent_initial_call=True,
)
def update_tiles1(tiles):
    if tiles == "OSM":
        return dl.TileLayer()
    else:
        return CARTO_TILES


if __name__ == "__main__":
    app.run_server(debug=True)

Scenario 1: before changing zoom value

  • Select OSM in the dropdown to load default dl.TileLayer
    • See that the tiles fail to load
    • Use scroll to zoom out
    • See that the tiles are loaded correctly
  • Select CARTO in the dropdown to load Carto tile layer.
    • See that the tiles loaded don't correspond to the center coordinates
    • Use scroll to zoom in/out
    • See that the tiles are loaded correctly

Scenario 2: using zoomControl tooltip to have integer zoom values

  • Zoom in using the zoomControl tooltip. (Now zoom value will be equal to 18 and any zoom in/out using this control will be an integer value)
  • Select OSM in the dropdown to load default dl.TileLayer
    • See that the tiles are loaded correctly
  • Select CARTO in the dropdown to load Carto tile layer.
    • See that the tiles are loaded correctly

Demo

Screen.Recording.2024-06-04.at.20.34.21.mov

Expected result

The zoom value shouldn't be used to build the tiles requests in any case as these requests are incorrect. It's closest zoom level should be used instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant