Skip to content

Filter Features Within a Layer ​

Show or hide specific map features dynamically using setFilter() without reloading data.

How It Works ​

setFilter() applies a filter expression to a layer — only features that match the expression are displayed. The data stays in the source; only the rendering changes.

Basic Filter Patterns ​

javascript
// Show all features (clear filter)
map.setFilter('my-layer', null);

// Match exact string value
map.setFilter('my-layer', ['==', ['get', 'type'], 'capital']);

// Match boolean property
map.setFilter('my-layer', ['==', ['get', 'port'], true]);

// Numeric comparison
map.setFilter('my-layer', ['>=', ['get', 'population'], 1000000]);

// Multiple conditions (AND)
map.setFilter('my-layer', [
  'all',
  ['==', ['get', 'type'], 'capital'],
  ['>=', ['get', 'population'], 1000000]
]);

// Multiple conditions (OR)
map.setFilter('my-layer', [
  'any',
  ['==', ['get', 'type'], 'capital'],
  ['==', ['get', 'port'], true]
]);
javascript
const searchInput = document.getElementById('search');

searchInput.addEventListener('input', (e) => {
  const query = e.target.value.toLowerCase();

  if (!query) {
    map.setFilter('cities-layer', null);
    return;
  }

  // Filter by name containing the search text
  map.setFilter('cities-layer', [
    'in',
    query,
    ['downcase', ['get', 'name']]
  ]);
});

Complete Example ​

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
    <script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
    <style>#map { height: 500px; width: 100%; }</style>
  </head>
  <body>
    <div id="map"></div>
    <div>
      <button onclick="filterBy('all')">All</button>
      <button onclick="filterBy('capital')">Capitals</button>
      <button onclick="filterBy('city')">Cities</button>
    </div>
    <script>
      const map = new mapmetricsgl.Map({
        container: 'map',
        style: '<StyleFile_URL_with_Token>',
        center: [5, 48],
        zoom: 4
      });

      map.on('load', () => {
        map.addSource('cities', {
          type: 'geojson',
          data: {
            type: 'FeatureCollection',
            features: [
              { type: 'Feature', properties: { name: 'Paris', type: 'capital' }, geometry: { type: 'Point', coordinates: [2.349902, 48.852966] } },
              { type: 'Feature', properties: { name: 'London', type: 'capital' }, geometry: { type: 'Point', coordinates: [-0.1276, 51.5074] } },
              { type: 'Feature', properties: { name: 'Hamburg', type: 'city' }, geometry: { type: 'Point', coordinates: [9.9937, 53.5511] } },
              { type: 'Feature', properties: { name: 'Lyon', type: 'city' }, geometry: { type: 'Point', coordinates: [4.8357, 45.764] } },
            ]
          }
        });

        map.addLayer({
          id: 'cities-layer',
          type: 'circle',
          source: 'cities',
          paint: {
            'circle-radius': 10,
            'circle-color': ['match', ['get', 'type'], 'capital', '#ef4444', '#3b82f6'],
            'circle-stroke-width': 2,
            'circle-stroke-color': '#fff'
          }
        });
      });

      function filterBy(type) {
        if (type === 'all') {
          map.setFilter('cities-layer', null);
        } else {
          map.setFilter('cities-layer', ['==', ['get', 'type'], type]);
        }
      }
    </script>
  </body>
</html>
jsx
import React, { useEffect, useRef } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

const citiesData = {
  type: 'FeatureCollection',
  features: [
    { type: 'Feature', properties: { name: 'Paris', type: 'capital' }, geometry: { type: 'Point', coordinates: [2.349902, 48.852966] } },
    { type: 'Feature', properties: { name: 'London', type: 'capital' }, geometry: { type: 'Point', coordinates: [-0.1276, 51.5074] } },
    { type: 'Feature', properties: { name: 'Hamburg', type: 'city' }, geometry: { type: 'Point', coordinates: [9.9937, 53.5511] } },
    { type: 'Feature', properties: { name: 'Lyon', type: 'city' }, geometry: { type: 'Point', coordinates: [4.8357, 45.764] } },
  ]
};

const FilterLayer = () => {
  const mapContainer = useRef(null);
  const map = useRef(null);

  useEffect(() => {
    if (map.current) return;

    map.current = new mapmetricsgl.Map({
      container: mapContainer.current,
      style: '<StyleFile_URL_with_Token>',
      center: [5, 48],
      zoom: 4
    });

    map.current.on('load', () => {
      map.current.addSource('cities', { type: 'geojson', data: citiesData });

      map.current.addLayer({
        id: 'cities-layer',
        type: 'circle',
        source: 'cities',
        paint: {
          'circle-radius': 10,
          'circle-color': ['match', ['get', 'type'], 'capital', '#ef4444', '#3b82f6'],
          'circle-stroke-width': 2,
          'circle-stroke-color': '#fff'
        }
      });
    });

    return () => { map.current?.remove(); map.current = null; };
  }, []);

  const filterBy = (type) => {
    if (!map.current) return;
    if (type === 'all') {
      map.current.setFilter('cities-layer', null);
    } else {
      map.current.setFilter('cities-layer', ['==', ['get', 'type'], type]);
    }
  };

  return (
    <div>
      <div ref={mapContainer} style={{ height: '500px', width: '100%' }} />
      <div style={{ marginTop: '8px', display: 'flex', gap: '8px' }}>
        <button onClick={() => filterBy('all')} style={{ padding: '8px 16px', background: '#3b82f6', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer' }}>All</button>
        <button onClick={() => filterBy('capital')} style={{ padding: '8px 16px', background: '#ef4444', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer' }}>Capitals</button>
        <button onClick={() => filterBy('city')} style={{ padding: '8px 16px', background: '#22c55e', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer' }}>Cities</button>
      </div>
    </div>
  );
};

export default FilterLayer;

For more information, visit the MapMetrics GitHub repository.