MapSnippets logoMapSnippets logo

Geofencing with Leaflet

Leaflet

Define a polygon boundary and check whether a point is inside or outside the geofence.

progress_activityLoading map...
const map = L.map('map').setView([48.8566, 2.3522], 13);
L.tileLayer('https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=YOUR_MAPTILER_KEY', {
  tileSize: 256,
  attribution: '&copy; <a href="https://www.maptiler.com/">MapTiler</a> &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>'
}).addTo(map);
const fence = [[48.865, 2.335], [48.865, 2.365], [48.845, 2.365], [48.845, 2.335]];
L.polygon(fence, { color: '#e63946', fillOpacity: 0.15, weight: 2 }).addTo(map).bindPopup('Geofence zone');
function pointInPolygon(lat, lng, poly) {
  let inside = false;
  for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
    const [yi, xi] = poly[i], [yj, xj] = poly[j];
    if ((yi > lng) !== (yj > lng) && lat < (xj - xi) * (lng - yi) / (yj - yi) + xi) inside = !inside;
  }
  return inside;
}
map.on('click', (e) => {
  const inside = pointInPolygon(e.latlng.lat, e.latlng.lng, fence);
  L.popup()
    .setLatLng(e.latlng)
    .setContent(inside ? '<b style="color:#4CAF50">Inside zone</b>' : '<b style="color:#e63946">Outside zone</b>')
    .openOn(map);
});

How it works

A geofence is a virtual boundary defined by a polygon. This example draws a rectangular fence zone over central Paris using L.polygon(). When the user clicks anywhere on the map, a ray-casting algorithm determines whether the click point is inside or outside the polygon.

The pointInPolygon() function implements the classic ray-casting test: it casts a horizontal ray from the test point and counts how many polygon edges it crosses. An odd count means inside, even means outside. This works for any simple polygon: convex or concave.

A popup displays the result at the clicked location with color-coded text. In a real application, you would combine this with the Geolocation API to test the user’s live position against the fence.

Key APIs

API Description Docs
L.polygon() Draw a polygon on the map leafletjs.com/reference.html#polygon
map.on('click') Listen for map click events leafletjs.com/reference.html#map-click
L.popup() Create a standalone popup leafletjs.com/reference.html#popup

FAQ

Can I use complex polygon shapes like neighborhoods?

Yes. Replace the rectangle coordinates with any GeoJSON polygon ring. The ray-casting algorithm works with arbitrary simple polygons.

How do I check the user’s live GPS position against the fence?

Combine with map.locate({ watch: true }) and test each locationfound event’s coordinates against the polygon using the same pointInPolygon() function.

Does this work for polygons with holes?

The basic ray-casting algorithm handles the outer ring. For polygons with holes, run the test against each ring and XOR the results.

Common mistakes

  • Defining fence coordinates as [lng, lat]: Leaflet polygons use [lat, lng] order
  • Not closing the polygon: Leaflet auto-closes it, but the ray-casting function expects the last point to connect back to the first
  • Using this for server-side validation: client-side geofencing is easy to bypass; always validate on the server too
auto_awesome

Build maps using Leaflet with AI

Generate code like this geofencing with leaflet example using the Leaflet skill in your IDE.