Point filtering by property
Filter thousands of features in real time to quickly and easily find those with a property that meets your search criteria.
NPM module setup
npm install --save @maptiler/sdk
import { Map, MapStyle, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
const map = new Map({
container: 'map',
zoom: 10,
center: [-118, 34],
style: MapStyle.DATAVIZ.LIGHT,
geolocateControl: false,
});
let studentMax = 0;
map.on('load', async () => {
const dataRes = await fetch('https://docs.maptiler.com/sdk-js/assets/Public_School_Characteristics_2020-21_los_angeles_name_number.geojson');
const data = await dataRes.json();
for (let i = 0; i < data.features.length; i += 1) {
studentMax = Math.max(studentMax, data.features[i].properties.students);
}
$("#sampleSlider").ionRangeSlider({
type: "double",
skin: "round",
hide_min_max: false,
force_edges: true,
min: 0,
max: studentMax,
grid: false,
onChange: function (values) {
const source = map.getSource('school_source');
const {from, to} = values;
if (!source) return;
filterBy(from, to);
//const filteredData = filterData(data, from, to);
//source.setData(filteredData);
},
});
// add a clustered GeoJSON source for a sample set of earthquakes
map.addSource('school_source', {
'type': 'geojson',
'data': data,
});
map.addLayer({
'id': 'school_point',
'type': 'circle',
'source': 'school_source',
'minzoom': 0,
'paint': {
'circle-pitch-alignment': "map",
// Size circle radius by earthquake magnitude and zoom level
'circle-radius': [
'interpolate',
['linear'],
['zoom'],
// 0, ['interpolate', ['linear'], ['get', 'students'], 10, 0.1, 4000, 0.01],
4, [
'interpolate',['linear'], ['get', 'students'],
10, 0.01,
4000, 0.1
],
8, [
'interpolate',['linear'], ['get', 'students'],
10, 1,
4000, 4
],
16, [
'interpolate', ['linear'], ['get', 'students'],
10, 5,
4000, 50
]
],
// Color circle by earthquake magnitude
'circle-color': [
'interpolate',
['linear'],
['get', 'students'],
0, "rgba(255, 255, 0, 0)",
50, "rgba(255, 255, 0, 1)",
2000, "rgba(255, 0, 0, 1)",
5000, "rgba(50, 0, 0, 1)",
],
// 'circle-stroke-color': 'white',
'circle-stroke-width': 0,
// Transition from heatmap to circle layer by zoom level
'circle-opacity': [
'interpolate',
['linear'],
['zoom'],
3, 0, // zoom, opacity
5, 0.3,
8, 0.8,
]
}
});
});
map.on("mouseenter", "school_point", (e) => {
if (!e.features) return;
if (!e.features.length) return;
if (!e.features[0].properties) return;
if (!e.features[0].properties.name) return;
if (!e.features[0].properties.students) return;
const display = `${e.features[0].properties.name} (${e.features[0].properties.students} students)`
document.querySelector(".infoContainer").innerHTML = display;
document.querySelector(".infoContainer").style.display = "block";
});
map.on("mouseleave", "school_point", (e) => {
document.querySelector(".infoContainer").innerHTML = "";
document.querySelector(".infoContainer").style.display = "none";
});
function filterBy(min, max) {
const filters = [
'all',
[">=", 'students', min],
["<=", 'students', max]
];
map.setFilter('school_point', filters);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex">
<title>Point filtering by property | NPM example</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="infoContainer"></div>
<div class="sliderContainer">
<input type="text" id="sampleSlider" />
</div>
<div id="map"></div>
<script type="module" src="./main.js"></script>
</body>
</html>
body {margin: 0; padding: 0;}
#map {position: absolute; top: 0; bottom: 0; width: 100%;}
.infoContainer {
color: #858e96;
z-index: 1;
background-color: rgb(255 255 255 / 60%);
position: absolute;
font-size: 22px;
font-family: sans-serif;
width: 80%;
height: 26px;
left: 0;
right: 0;
top: 0;
margin: 10px auto;
border-radius: 3px;
padding: 8px;
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
text-align: center;
}
.sliderContainer {
z-index: 1;
background-color: rgb(255 255 255 / 60%);
position: absolute;
font-size: 30px;
font-family: sans-serif;
padding: 10px;
width: 80%;
height: 50px;
left: 0;
right: 0;
bottom: 0;
margin: 30px auto;
border-radius: 3px;
backdrop-filter: blur(10px);
}