Search code examples
mapboxmapbox-gl

How to set filter only on country boundaries with US worldview?


I'm using Mapbox GL to color dynamically countries. Some of the countries are red, some are green.

For this, I'm using the country-boundaries-v1 source, then I use the iso_3166-1 data from country-boundaries to set a filter on the layers that use the country-boundaries source.

This is the code where I add my layers:

addLayers (map, layers) {
  layers.forEach((layer) => {
    map.addLayer({
      id: layer.id,
      source: layer.source,
      'source-layer': layer.sourceLayer,
      layout: {
        visibility: 'none'
      },
      type: 'fill',
      paint: {
        'fill-opacity': 0.5
      }
    }, 'country-label')
  })
},

And there is where I make visible my layer, add the color and set my filter on a list of iso_3166-1 codes:

map.setLayoutProperty(state.id, 'visibility', 'visible')
map.setPaintProperty(state.id, 'fill-color', this.layerColor(formattedState))
map.setFilter('positive-countries', ['in', 'iso_3166_1', 'FR', 'BE', 'IN', 'CN', 'JP'])

The problem is that when I add the 'fill-color' property on my layers that have reduced opacity, countries with different worldview (like China, Japan, India) therefore have layers that overlap. The result is that some countries, instead of having a layer with an opacity of 0.6, have 3 with an opacity of 0.6, which makes them opaque.

I tried to add this :

map.setFilter('positive-countries', ['match', ['get', 'worldview'], ['all', 'US'], true, false])

Hope Mapbox only uses the US worldview, but it doesn't work.

Here is a screenshot of my map so you can see the problem:

map

As you can see, countries like China, India and Japan have multiple layers because there's multiple worldview for these countries, so they look different than others.

Does anyone know if what I want to do is possible?

EDIT:

I tried this:

const filters = [
  'any',
  ['in', 'iso_3166_1', 'MA', 'BR'],
  ['==', 'all', ['get', 'worldview']],
  ['in', 'US', ['get', 'worldview']]
]

map.setFilter('positive-countries', filters)

But I got these errors:

mapbox-gl.js:31 Error: layers.positive-countries.filter[2][2]: string, number, or boolean expected, array found
mapbox-gl.js:31 Error: layers.positive-countries.filter[3][2]: string, number, or boolean expected, array found

If I remove ['in', 'iso_3166_1', 'MA', 'BR'], there are no more errors but of course I have no applied filter on my map.

So, I tried this:

const filters = [
  'any',
  ['==', 'all', ['get', 'worldview']],
  ['in', 'US', ['get', 'worldview']]
]

map.setFilter(params['id'], filters)
map.setFilter(params['id'], ['in', 'iso_3166_1', 'MA', 'BR'])

but the result is the same as without filter on the worldview...


Solution

  • If someone else is facing the same problem, this is the solution:

    const filters = [
      'all',
      ['match', ['get', 'worldview'], ['all', 'US'], true, false],
      ['match', ['get', 'iso_3166_1'], ['MA', 'BR'], true, false]
    ]
    
    this.map.setFilter(layerId, filters)
    

    Only the countries as seen by the USA are then visible