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

Style Parsing #164

Merged
merged 13 commits into from
Aug 9, 2023
Merged

Style Parsing #164

merged 13 commits into from
Aug 9, 2023

Conversation

RobertOrthofer
Copy link
Contributor

This feature implements style parsing for vector layers. This is achieved by combining ol-mapbox-style as a parser for mapbox styles, while keeping the simpler layer and source definition that is already implemented in the project.

The basic idea is that the properties of our custom layer-JSON-format can, additionally to the id and the source of the layer, also hold a style object, which should be a simple mapbox style object. All layers from that object should reference the same source. This mabox style will not override the source, if no source is defined, a dummy source will be added, since it is needed to create a valid mapbox style object.

This solution is meant to style vector data (Vector or VectorTile sources). Style expressions can be used to implement more complex and dynamic styles, like referencing object properties of features for dynamic styling or filtering.

@silvester-pari
Copy link
Collaborator

silvester-pari commented Jul 26, 2023

Thank you @RobertOrthofer, a quick test didn't work on my end, with the console error Uncaught (in promise) Error: Can only apply to VectorLayer or VectorTileLayer (at apply.js:238:13). Other than that I will have a more in-depth look this afternoon.

Edit: Sorry, my bad, forgot to npm install... 🙈 Error went away.

Copy link
Collaborator

@silvester-pari silvester-pari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After more experimentation, I think this is a great solution! I think I would like it better if the property name was different, since style could be a property that is natively supported by OL (thinking of flat styles that could look very similar and cause confusion). What do you think if we make it really explicit, by introducing an e.g. mapbox-style property? So a layer JSON with style would be native OL style, and one with mapbox-style would apply a mapbox style instead.

{
  "type": "Vector",
  "mapbox-style": {
    // the mapbox style
  } 
}

Another solution would be to pass a mapbox property into the native style, something like:

{
  "type": "Vector",
  "style": {
    "mapbox": {
      // the mapbox style
    }
  } 
}

What do you prefer?

@RobertOrthofer
Copy link
Contributor Author

RobertOrthofer commented Jul 26, 2023

Originally i was thinking about using the "style"-property as both, accepting either mapbox styles but also the flat styles. This would also prevent users from defining both, which might lead to unwanted results.

Differentiating between the style notations should be trivial, as the "version" property is mandatory for mapbox styles, but not allowed in ol-styles.

@silvester-pari
Copy link
Collaborator

silvester-pari commented Jul 27, 2023

Originally i was thinking about using the "style"-property as both, accepting either mapbox styles but also the flat styles. This would also prevent users from defining both, which might lead to unwanted results.

Differentiating between the style notations should be trivial, as the "version" property is mandatory for mapbox styles, but not allowed in ol-styles.

Right, but in the current test the style is set as a property, not as a style - there is a difference between those two things:

console.log(layer.getStyle()) // gets the layer style
console.log(layer.get("style")) // gets a custom "style" property

So in the current state, the user could both apply a style and a style property. What we could do is to check a bit sooner (during the layer generation), if the style includes e.g. a "version", then don't apply it as a style but apply it with mapbox-styles at a later stage.
I think part of the confusion comes from the different ways of defining properties. It is totally fine to add custom proeprties directly to the layer, but there are special properties that are used otherwise (such as style):

const layer = new VectorLayer({
  source: source,
  style: styles,
  id: "foo", // custom property
  title: "bar" // custom property
});
console.log(layer.get("id"); // returns "foo"
console.log(layer.get("title"); // returns "bar"
console.log(layer.get("style"); // returns undefined
console.log(layer.getStyle()); // returns layer style

versus

const layer = new VectorLayer({
  source: source,
  style: styles,
  properties: {
    id: "foo", // custom property
    title: "bar", // custom property
    style: "baz" // custom property
  }
});
console.log(layer.get("id"); // returns "foo"
console.log(layer.get("title"); // returns "bar"
console.log(layer.get("style"); // returns "baz"
console.log(layer.getStyle()); // returns layer style

👍 from my side to have both defined as style property in the JSON structure (not properties.style), but then the order of doing things needs to change a bit 😊

@RobertOrthofer
Copy link
Contributor Author

Ah, now i understand. Yes, that would be best, i will update the code.

@silvester-pari
Copy link
Collaborator

Thank you for the updates, works well with Vector layers but I am struggling to make it work with VectorTile layers - trying to find out what the issue could be.

@RobertOrthofer
Copy link
Contributor Author

To sum it up: The issue was the missing flag updateSource: false and a missing source-layer-prop in the mapbox style. Also there might have been a mismatch between ol and ol-mapbox-style, on my side also problems with the npm-cache.
The map-Element as well as the Tests have now been updated.

@silvester-pari silvester-pari changed the base branch from main to map/main August 9, 2023 22:20
Copy link
Collaborator

@silvester-pari silvester-pari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your work!

"properties": {
"id": "regions"
"id": "regions",
"style": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if here in the test we could use a minimal example to show what the minimum fields are to make this work. I understand that version is necessary, but other things are not. Also, the source name does not need to match the layer id, maybe it's better to explicitly show this in the test, for example:

{
  version: 8,
  layers: [
    {
      type: "fill",
      source: "foobar",
      paint: {
        "fill-color": ["get", "COLOR"],
        "fill-opacity": 1,
      },
    },
    {
      type: "line",
      source: "foobar",
      paint: {
        "line-color": "#fff",
        "line-width": 1.5,
      },
    },
  ],
}

Maybe, for convenience, the source property could be automatically generated with an arbitrary string, since it serves no purpose. Or am I missing a functionality here?

@silvester-pari silvester-pari merged commit 5d41425 into map/main Aug 9, 2023
2 checks passed
@silvester-pari silvester-pari deleted the map/feature/styles branch August 9, 2023 22:49
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

Successfully merging this pull request may close these issues.

2 participants