emilhe / dash-leaflet

MIT License
214 stars 40 forks source link

Vector tile layer #255

Open emilhe opened 1 month ago

emilhe commented 1 month ago

The PR introduces a VectorTileLayer component, based on this library, which enables rendering of (protobuf) vector tiles.

import dash_leaflet as dl
from dash import Dash
from dash_extensions.javascript import assign

eventHandlers = dict(click=assign("function(e, ctx){console.log(e); console.log(ctx);}"))

app = Dash()
app.layout = dl.Map(
    [
        dl.TileLayer(),
        dl.VectorTileLayer(url="https://openinframap.org/tiles/{z}/{x}/{y}.pbf", maxDetailZoom=6, style={}, eventHandlers=eventHandlers),
    ],
    center=[56, 10],
    zoom=8,
    style={"height": "50vh"},
)

if __name__ == "__main__":
    app.run_server(debug=True)
emilhe commented 1 month ago

@Eric-UW-CRL thanks for the feedback! There is nothing wrong with your code - i just didn't get to event handlers in the first take. If you bump to the next rc version,

pip install dash-leaflet==1.0.17rc2

your code should work. For reference, I have updated the example in the PR post to use event handlers. Note, I have not added any default event handlers yet (i.e. you don't have e.g. an n_clicks proper like many other components).

emacollins commented 1 month ago

@emilhe I see! I gave the update a try, and my event handler now works on clicks.

I was looking at the default event handlers for the GeoJSON components, and maybe it makes sense to add the same defaults for this? I imagine users would primarily want to click on the features or mouse over them to get the properties. My simple attempt using a custom event handler was as follows. This gives me enough control however to get the data from the features that I need.

eventHandlers = dict(
    click=assign(
        "function(e, ctx){ctx.setProps({clickData: e.layer.feature.properties})}"
    )
)
kepiej commented 3 weeks ago

This would be a super welcome addition to this awesome package! :)

I have a use case where the tile layer also accepts query parameters (i.e., passed in the url in the form "?param1=value1"). Is there any way that we can pass the values of these query parameters dynamically via a dash callback (e.g., depending on selected user input)? Is this what fetchOptions is meant for? (I don't seem to get it to work ... 😢 )

emilhe commented 3 weeks ago

This would be a super welcome addition to this awesome package! :)

I have a use case where the tile layer also accepts query parameters (i.e., passed in the url in the form "?param1=value1"). Is there any way that we can pass the values of these query parameters dynamically via a dash callback (e.g., depending on selected user input)?

Is this what fetchOptions is meant for? (I don't seem to get it to work ... 😢 )

Did you try just passing the URL with parameters included?

FetchOptions are options passed to the request itself (method, headers, etc.)

kepiej commented 3 weeks ago

This would be a super welcome addition to this awesome package! :) I have a use case where the tile layer also accepts query parameters (i.e., passed in the url in the form "?param1=value1"). Is there any way that we can pass the values of these query parameters dynamically via a dash callback (e.g., depending on selected user input)? Is this what fetchOptions is meant for? (I don't seem to get it to work ... 😢 )

Did you try just passing the URL with parameters included?

Yes, that works but is not exactly what I'm looking for: I would like to be able to change the value of the query parameter dynamically (e.g., through a dash callback) when a user makes a different selection in a dropdown box. So the value in "?param1=value" would be modified by user interaction.

emilhe commented 3 weeks ago

In that case, I guess if the URL was made dynamic (i.e that it can be changed by a callback), that would support your use case also?

kepiej commented 3 weeks ago

In that case, I guess if the URL was made dynamic (i.e that it can be changed by a callback), that would support your use case also?

Yes, absolutely! 👍 I tried modifying it with a callback but that doesn't work currently. Hence my question here. :)