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

Add style callbacks for VectorTileLayer #744

Open
deeplook opened this issue Nov 4, 2020 · 11 comments
Open

Add style callbacks for VectorTileLayer #744

deeplook opened this issue Nov 4, 2020 · 11 comments

Comments

@deeplook
Copy link
Contributor

deeplook commented Nov 4, 2020

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.

@martinRenou
Copy link
Member

martinRenou commented Nov 5, 2020

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.

@deeplook
Copy link
Contributor Author

deeplook commented Nov 5, 2020

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.

@martinRenou
Copy link
Member

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.

@deeplook
Copy link
Contributor Author

deeplook commented Nov 5, 2020

but I personally don't wish anyone to have to write JavaScript.

I surely share that feeling. ;) How about a JupyterLab extension, then? ;)

@martinRenou
Copy link
Member

How about a JupyterLab extension, then? ;)

What do you mean? ipyleaflet already contains a JupyterLab extension

@deeplook
Copy link
Contributor Author

deeplook commented Nov 5, 2020

Sure, but maybe the extension could cover the more intricate JS code...

@martinRenou
Copy link
Member

What kind of API do you have in mind?

@lopezvoliver
Copy link
Contributor

lopezvoliver commented Mar 13, 2024

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.

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:

image

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?

@lopezvoliver
Copy link
Contributor

This is currently possible using folium with the vectorGrid plugin:

image

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,
};
}
}
}'''

@lopezvoliver
Copy link
Contributor

lopezvoliver commented Jun 11, 2024

@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).

@martinRenou
Copy link
Member

Definitely, would you like to try a PR to ipyleaflet?

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

3 participants