maplibre / maplibre-gl-js

MapLibre GL JS - Interactive vector tile maps in the browser
https://maplibre.org/maplibre-gl-js/docs/
Other
6.74k stars 723 forks source link

Change “fill-color”、“fill-pattern” with "feature-state" did not get the correct result #4930

Open beikehanbao23 opened 4 weeks ago

beikehanbao23 commented 4 weeks ago

maplibre-gl-js version: 4.7.1 browser: Google Chrome 130.0.6723.70

Hello everyone:

I want to change the fill image of the polygon, using the fill-pattern attribute work with feature-state. However, I did not get the correct result: "feature-state" is different, but the "fill-pattern" is the same.. image

image

function fillPatternFromFeatureState (){
    map.setPaintProperty('layerid', 'fill-pattern', ["match", ["feature-state", 'for-pattern'],
      "cat1", "airport_11",
      'cat2', "bar_11",
      'cat3', 'bakery_11',
      'archery_11'] )
}

When I use the properties(name) that come with "feature" , it can be achieved .

image

function fillPatternFromFeatureProperties(){
    map.setPaintProperty('layerid', 'fill-pattern', ["match", ["get", 'name'],
      "cat1", "airport_11",
      'cat2', "bar_11",
      'cat3', 'bakery_11',
      'archery_11'])
}

Steps:

  1. Load demo GeoJSON, which contains three different polygons with different name attributes
  2. Assign three different polygon "feature-state" attributes

Link to Demonstration https://jsbin.com/xebocucufi/3/edit?html,console,output

First question, hope I've made it clear. I'm not sure if it's a bug. Any help is welcome.

HarelM commented 4 weeks ago

Checkout the docs: https://maplibre.org/maplibre-style-spec/layers/#fill-color https://maplibre.org/maplibre-style-spec/layers/#fill-pattern You can see that fill color support feature state while pattern doesn't. Here's an old issue about this: https://github.com/mapbox/mapbox-gl-js/issues/7207

I've looked in the code to better understand why this is not supported and I think the problem is that feature-state is stored in the main thread while the worker is parsing the tiles and preparing the images for pattern it can only do that for a feature without its state, as can be seen here: https://github.com/maplibre/maplibre-gl-js/blob/9d9a600bf7d2f42d6d171d3e35aa622fb8e58205/src/data/bucket/pattern_bucket_features.ts#L41

Not sure it's helpful to you, but feel free to explore a way to solve this if this interest you.

beikehanbao23 commented 4 weeks ago

@HarelM Thank you for your help.

Will the ' fill-pattern' support the feature-state in the future?

If not, what suggestions are there to implement different fill-patterns, about 10+ different images.

HarelM commented 4 weeks ago

If someone would be interested enough to contribute a PR it might be supported, but otherwise, very low chances. For different fill patterns you might want to use different geojson features, html markers or other dynamic solutions that are not based on feature-state...

beikehanbao23 commented 4 weeks ago

Thanks

I solved this problem by putting fill values into the attributes object.

function fillPatternFromFeatureProperties(){
    map.setPaintProperty('layerid', 'fill-pattern', ["match", ["get", 'fill-img'],
      "cat1", "airport_11",
      'cat2', "bar_11",
      'cat3', 'bakery_11',
      'archery_11'])
}