ipyleaflet
ipyleaflet copied to clipboard
Add style callbacks for VectorTileLayer
Styling for vector tiles can be pretty complex and the current implementation of VectorTileLayer only allows for one static style per "tile layer" e.g. "roads". This is a severe limitation as one cannot exploit the rich feature properties stored in vector tiles, e.g. to render different types of roads individually. The Leaflet VectorGrid plugin does support function callbacks for more dynamic styling as described here: https://leaflet.github.io/Leaflet.VectorGrid/vectorgrid-api-docs.html#styling-vectorgrids. So I think it should be possible to wrap this functionality and expose it in ipyleaflet, too, in a way similar to the style_callback parameter for GeoJSON layer.
I don't think this is technically doable without transpiling the Python code into JS.
In GeoJSON we can modify the data with a style_callback because they are available in the Python process. In the VectorTileLayer we don't have access to the tiles data in the Python process, something like a style_callback would need to be performed in JS.
Also, we provide access to styling the VectorTileLayer already IIRC.
In the VectorTileLayer we don't have access to the tiles data in the Python process
But the VectorGrid plugin has access to it or it couldn't apply the styling functions mentions on the page above. Maybe it's possible to have deeper access to this plugin?
Also, we provide access to styling the VectorTileLayer already IIRC.
To some degree at least. Maybe @omanges can help.
But the VectorGrid plugin has access to it or it couldn't apply the styling functions mentions on the page above
Only JavaScript side.
A style_callback feature you are requesting would need to be provided in Python I guess. Unless we ask people to write JavaScript, but I personally don't wish anyone to have to write JavaScript.
but I personally don't wish anyone to have to write JavaScript.
I surely share that feeling. ;) How about a JupyterLab extension, then? ;)
How about a JupyterLab extension, then? ;)
What do you mean? ipyleaflet already contains a JupyterLab extension
Sure, but maybe the extension could cover the more intricate JS code...
What kind of API do you have in mind?
But the VectorGrid plugin has access to it or it couldn't apply the styling functions mentions on the page above
Only JavaScript side.
A
style_callbackfeature you are requesting would need to be provided in Python I guess. Unless we ask people to write JavaScript, but I personally don't wish anyone to have to write JavaScript.
Are there any plans for this? I wouldn't mind providing a small callback function in Javascript if it means I can do conditional styling.
For example, I would like to be able to do something like this:
var vectorTileOptions = {
minZoom: 0,
maxNativeZoom: 13,
interactive: true,
vectorTileLayerStyles: {
// Define your custom styles for the vector tile layer
"2015ETm3": function (properties, zoom) {
// Function to style the fields in different colors
// based on one attribute (e.g. fieldUse).
var fieldColor = "#ffffcc"; // default color
if (properties.fieldUse >= 0.25) {
fieldColor = "#c2e699";
}
if (properties.fieldUse >= 0.5) {
fieldColor = "#78c679";
}
if (properties.fieldUse >= 0.75) {
fieldColor = "#31a354";
}
if (properties.fieldUse >= 1) {
fieldColor = "#006837";
}
return {
fillOpacity: 1,
fillColor: fieldColor,
fill: true,
weight: 1,
color: "white",
opacity: 1,
};
},
},
};
is this currently possible in ipyleaflet? what other options are there for achieving this?
This is currently possible using folium with the vectorGrid plugin:
where options is a string including the JS function:
options='''{
"vectorTileLayerStyles": {
"2015ETm3": function(f) {
var fieldColor = "#ffffcc";
if (f.fieldUse >= 0.25) {
fieldColor = "#c2e699";
}
if (f.fieldUse >= 0.5) {
fieldColor = "#78c679";
}
if (f.fieldUse >= 0.75) {
fieldColor = "#31a354";
}
if (f.fieldUse >= 1) {
fieldColor = "#006837";
}
return {
fillOpacity: 1,
fillColor: fieldColor,
fill: true,
weight: 1,
color: "white",
opacity: 1,
};
}
}
}'''
@martinRenou
Would it be possible to add some small typescript code (potentially just one line?) in LeafletVectorTileLayerModel that sets vectorTileLayerStyles either as a dictionary (as it currently is) OR a string that gets converted to a dictionary?
e.g., similar as what the folium vectorgrid plugin does here
This way the user has the option to define the vector_tile_layer_styles as a string and optionally include logic for styling features (in javascript).
Definitely, would you like to try a PR to ipyleaflet?