MapSnippets logoMapSnippets logo

Geofencing with MapTiler SDK

MapTiler SDK

Define a polygon boundary with MapTiler SDK and check whether a clicked point falls inside or outside the geofence.

progress_activityLoading map...
maptilersdk.config.apiKey = 'YOUR_MAPTILER_KEY';
const map = new maptilersdk.Map({
  container: 'map',
  style: maptilersdk.MapStyle.STREETS,
  center: [-0.1276, 51.5074],
  zoom: 13
});
const fenceCoords = [[-0.15, 51.52], [-0.10, 51.52], [-0.10, 51.50], [-0.15, 51.50], [-0.15, 51.52]];
function pointInPolygon(lng, lat, ring) {
  let inside = false;
  for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
    const [xi, yi] = ring[i], [xj, yj] = ring[j];
    if ((yi > lat) !== (yj > lat) && lng < (xj - xi) * (lat - yi) / (yj - yi) + xi) inside = !inside;
  }
  return inside;
}
map.on('load', () => {
  map.addSource('fence', { type: 'geojson', data: { type: 'Feature', geometry: { type: 'Polygon', coordinates: [fenceCoords] } } });
  map.addLayer({ id: 'fence-fill', type: 'fill', source: 'fence', paint: { 'fill-color': '#9C27B0', 'fill-opacity': 0.15 } });
  map.addLayer({ id: 'fence-line', type: 'line', source: 'fence', paint: { 'line-color': '#9C27B0', 'line-width': 2 } });
});
map.on('click', (e) => {
  const inside = pointInPolygon(e.lngLat.lng, e.lngLat.lat, fenceCoords);
  new maptilersdk.Popup()
    .setLngLat(e.lngLat)
    .setHTML(inside ? '<b style="color:#4CAF50">Inside zone</b>' : '<b style="color:#e63946">Outside zone</b>')
    .addTo(map);
});

How it works

A geofence polygon is defined as a GeoJSON coordinate ring and rendered using addSource and addLayer inside the map’s load event. The fence is visualized with a semi-transparent fill and a solid border in the SDK’s brand color.

When the user clicks the map, the pointInPolygon() function uses the ray-casting algorithm to determine whether the click falls inside the fence. A popup displays the result with color-coded text. The coordinate ring uses [lng, lat] order, consistent with GeoJSON and the MapTiler SDK.

For a real geofencing application, pair this with navigator.geolocation.watchPosition() to continuously test the user’s GPS position against the boundary.

Key APIs

API Description Docs
map.addSource() Add a GeoJSON data source docs.maptiler.com/sdk-js/api/
map.addLayer() Add fill or line layer docs.maptiler.com/sdk-js/api/
maptilersdk.Popup Display result at click location docs.maptiler.com/sdk-js/api/

FAQ

Can I load the fence polygon from an external GeoJSON file?

Yes. Fetch the GeoJSON with fetch() and pass the parsed object as the data property of addSource. The fence renders as soon as the data loads.

How do I detect when the user enters or exits the zone?

Track the previous inside/outside state. On each position update, compare the new result with the stored state to detect transitions and fire enter/exit callbacks.

Common mistakes

  • Using [lat, lng] instead of [lng, lat]: MapTiler SDK and GeoJSON both use longitude first
  • Not closing the GeoJSON polygon ring: the first and last coordinates must be identical
  • Adding sources and layers before the load event: the map style is not ready yet
auto_awesome

Build maps using MapTiler SDK with AI

Generate code like this geofencing with maptiler sdk example using the MapTiler SDK skill in your IDE.