---
title: "Point filtering by property | JavaScript maps SDK"
description: "Filter features in real time by property."
---

> For AI agents: a documentation index is available at [/llms.txt](https://docs.maptiler.com/llms.txt). Markdown versions of all pages are available by appending .md to any URL.

# 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

```bash
npm install --save @maptiler/sdk
```

#### main.js

```js
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);
}
```

#### index.html

```html
<!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>
```

#### style.css

```css
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);
}
```

### Basic JavaScript setup

```html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Point filtering</title>
<script src="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.umd.min.js"></script>
<link href="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js"></script>
<style>
  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);
  }
</style>
</head>
<body>
<div class="infoContainer"></div>
<div class="sliderContainer">
  <input type="text" id="sampleSlider" />
</div>
<div id="map"></div>

<script>
    maptilersdk.config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';

    const map = new maptilersdk.Map({
        container: 'map',
        zoom: 10,
        center: [-118, 34],
        style: maptilersdk.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);
    }

</script>
</body>
</html>
```

## Related examples

### [Get POIs information on click](https://docs.maptiler.com/sdk-js/examples/pois-info/)

Examples

Get POI information by clicking the map.

### [Point layer cluster (point helper)](https://docs.maptiler.com/sdk-js/examples/helper-point-cluster/)

Examples

Add clustered point layer using MapTiler point helper.

### [Heatmap layer (heatmap helper)](https://docs.maptiler.com/sdk-js/examples/helper-heatmap-minimal/)

Examples

Quickly add a heatmap layer using the heatmap helper.
