Filter Features by Toggle List
Toggle category buttons to show or hide specific feature types on the map using setFilter().
Toggle categories:
Filter by Active Categories
Track which categories are selected, then build a filter expression:
javascript
const activeCategories = new Set(['restaurant', 'cafe', 'hotel']);
function applyFilter() {
const active = [...activeCategories];
if (active.length === 0) {
// Hide everything
map.setFilter('places-layer', ['==', '1', '0']);
} else {
// Show features whose category is in the active list
map.setFilter('places-layer', [
'in',
['get', 'category'],
['literal', active]
]);
}
}
// Toggle a category on/off
function toggleCategory(category) {
if (activeCategories.has(category)) {
activeCategories.delete(category);
} else {
activeCategories.add(category);
}
applyFilter();
}Filter Expressions
javascript
// Show only restaurants
map.setFilter('layer', ['==', ['get', 'category'], 'restaurant']);
// Show restaurants OR cafes
map.setFilter('layer', [
'in',
['get', 'category'],
['literal', ['restaurant', 'cafe']]
]);
// Remove filter (show all)
map.setFilter('layer', null);
// Hide all
map.setFilter('layer', ['==', '1', '0']);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 class="cat-btn" data-cat="restaurant">Restaurant</button>
<button class="cat-btn" data-cat="cafe">Cafe</button>
<button class="cat-btn" data-cat="hotel">Hotel</button>
</div>
<script>
const map = new mapmetricsgl.Map({
container: 'map',
style: '<StyleFile_URL_with_Token>',
center: [2.3499, 48.853],
zoom: 13
});
const active = new Set(['restaurant', 'cafe', 'hotel']);
map.on('load', () => {
map.addSource('places', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{ type: 'Feature', properties: { category: 'restaurant' }, geometry: { type: 'Point', coordinates: [2.344, 48.856] } },
{ type: 'Feature', properties: { category: 'cafe' }, geometry: { type: 'Point', coordinates: [2.333, 48.854] } },
{ type: 'Feature', properties: { category: 'hotel' }, geometry: { type: 'Point', coordinates: [2.337, 48.860] } },
]
}
});
map.addLayer({
id: 'places-layer',
type: 'circle',
source: 'places',
paint: { 'circle-radius': 9, 'circle-color': '#3b82f6', 'circle-stroke-width': 2, 'circle-stroke-color': '#fff' }
});
function applyFilter() {
const list = [...active];
map.setFilter('places-layer', list.length
? ['in', ['get', 'category'], ['literal', list]]
: ['==', '1', '0']
);
}
document.querySelectorAll('.cat-btn').forEach(btn => {
btn.addEventListener('click', () => {
const cat = btn.dataset.cat;
active.has(cat) ? active.delete(cat) : active.add(cat);
applyFilter();
});
});
});
</script>
</body>
</html>jsx
import React, { useEffect, useRef, useState } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
const categories = ['restaurant', 'cafe', 'hotel'];
const placesData = {
type: 'FeatureCollection',
features: [
{ type: 'Feature', properties: { category: 'restaurant' }, geometry: { type: 'Point', coordinates: [2.344, 48.856] } },
{ type: 'Feature', properties: { category: 'cafe' }, geometry: { type: 'Point', coordinates: [2.333, 48.854] } },
{ type: 'Feature', properties: { category: 'hotel' }, geometry: { type: 'Point', coordinates: [2.337, 48.860] } },
]
};
const FilterByToggleList = () => {
const mapContainer = useRef(null);
const map = useRef(null);
const [active, setActive] = useState(new Set(categories));
useEffect(() => {
if (map.current) return;
map.current = new mapmetricsgl.Map({
container: mapContainer.current,
style: '<StyleFile_URL_with_Token>',
center: [2.3499, 48.853],
zoom: 13
});
map.current.on('load', () => {
map.current.addSource('places', { type: 'geojson', data: placesData });
map.current.addLayer({
id: 'places-layer', type: 'circle', source: 'places',
paint: { 'circle-radius': 9, 'circle-color': '#3b82f6', 'circle-stroke-width': 2, 'circle-stroke-color': '#fff' }
});
});
return () => { map.current?.remove(); map.current = null; };
}, []);
useEffect(() => {
if (!map.current) return;
const list = [...active];
map.current.setFilter?.('places-layer', list.length
? ['in', ['get', 'category'], ['literal', list]]
: ['==', '1', '0']
);
}, [active]);
const toggle = (cat) => {
setActive(prev => {
const next = new Set(prev);
next.has(cat) ? next.delete(cat) : next.add(cat);
return next;
});
};
return (
<div>
<div ref={mapContainer} style={{ height: '500px', width: '100%' }} />
<div style={{ marginTop: '8px', display: 'flex', gap: '8px' }}>
{categories.map(cat => (
<button
key={cat}
onClick={() => toggle(cat)}
style={{
padding: '6px 12px',
background: active.has(cat) ? '#3b82f6' : 'white',
color: active.has(cat) ? 'white' : '#3b82f6',
border: '2px solid #3b82f6',
borderRadius: '20px',
cursor: 'pointer'
}}
>
{cat}
</button>
))}
</div>
</div>
);
};
export default FilterByToggleList;For more information, visit the MapMetrics GitHub repository.