MapSnippets logoMapSnippets logo

Fuzzy Location

Display approximate location as a circle area instead of an exact pin Each library has its own approach: here's how they compare.

Quick Recommendations

Leaflet — The better fit for simple privacy circles using L.circle with radius in meters: the API directly supports geographic circles.

MapLibre GL JS — Ideal when the fuzzy area needs data-driven styling or must integrate with other GeoJSON layers in a WebGL-rendered map.

MapTiler SDK — Gives MapTiler SDK users MapLibre's circle polygon approach, plus simplified initialization.

At a Glance

LeafletMapLibreSDK
Coordinates[lat, lng][lng, lat][lng, lat]
RenderingDOM + Canvas (2D)WebGL (GPU, 60fps)WebGL (GPU, 60fps)
Bundle size~42 KB gzipped~250 KB gzipped~280 KB gzipped (includes MapLibre)
Learning curveEasiest (simple API, great tutorials)Moderate (source/layer model, expressions)Easy (MapLibre API with convenience helpers)
3D supportNo native 3D (2D only)Full: terrain, fill-extrusion, globe, skyFull (same as MapLibre)
Code lines152424

Code Snippets

Click a library to expand its code. Each snippet shows only the core logic: the scaffold handles HTML boilerplate.

Leaflet15 linesShow code
arrow_forwardFull example
const map = L.map('map').setView([51.5074, -0.1278], 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 realLat = 51.5074, realLng = -0.1278;
const offsetLat = realLat + (Math.random() - 0.5) * 0.01;
const offsetLng = realLng + (Math.random() - 0.5) * 0.01;
L.circle([offsetLat, offsetLng], {
  radius: 500,
  color: '#2196F3',
  fillColor: '#2196F3',
  fillOpacity: 0.15,
  weight: 2
}).addTo(map).bindPopup('Approximate location');
MapLibre GL JS24 linesShow code
arrow_forwardFull example
const map = new maplibregl.Map({
  container: 'map',
  style: 'https://api.maptiler.com/maps/streets-v4/style.json?key=YOUR_MAPTILER_KEY',
  center: [14.42, 50.08],
  zoom: 13
});
map.addControl(new maplibregl.NavigationControl());
function makeCircle(center, radiusKm, steps = 64) {
  const coords = [];
  for (let i = 0; i <= steps; i++) {
    const angle = (i / steps) * Math.PI * 2;
    const dx = radiusKm / (111.32 * Math.cos(center[1] * Math.PI / 180));
    const dy = radiusKm / 110.574;
    coords.push([center[0] + Math.cos(angle) * dx, center[1] + Math.sin(angle) * dy]);
  }
  return { type: 'Feature', geometry: { type: 'Polygon', coordinates: [coords] } };
}
map.on('load', () => {
  map.addSource('fuzzy', { type: 'geojson', data: makeCircle([14.42, 50.08], 0.5) });
  map.addLayer({ id: 'fuzzy-fill', type: 'fill', source: 'fuzzy',
    paint: { 'fill-color': '#2196F3', 'fill-opacity': 0.15 } });
  map.addLayer({ id: 'fuzzy-border', type: 'line', source: 'fuzzy',
    paint: { 'line-color': '#2196F3', 'line-width': 2, 'line-dasharray': [4, 2] } });
});
MapTiler SDK24 linesShow code
arrow_forwardFull example
maptilersdk.config.apiKey = 'YOUR_MAPTILER_KEY';
const map = new maptilersdk.Map({
  container: 'map',
  style: maptilersdk.MapStyle.STREETS,
  center: [2.3522, 48.8566],
  zoom: 13
});
function fuzzyCircle(center, radiusKm, points = 64) {
  const coords = [];
  for (let i = 0; i <= points; i++) {
    const angle = (i / points) * 2 * Math.PI;
    const dx = radiusKm / (111.32 * Math.cos(center[1] * Math.PI / 180));
    const dy = radiusKm / 110.574;
    coords.push([center[0] + dx * Math.cos(angle), center[1] + dy * Math.sin(angle)]);
  }
  return { type: 'Feature', geometry: { type: 'Polygon', coordinates: [coords] } };
}
map.on('load', () => {
  map.addSource('zone', { type: 'geojson', data: fuzzyCircle([2.3522, 48.8566], 0.5) });
  map.addLayer({ id: 'zone-fill', type: 'fill', source: 'zone',
    paint: { 'fill-color': '#9C27B0', 'fill-opacity': 0.2 } });
  map.addLayer({ id: 'zone-border', type: 'line', source: 'zone',
    paint: { 'line-color': '#9C27B0', 'line-width': 2, 'line-dasharray': [4, 2] } });
});

Things to Know

Implementation-specific details that matter for fuzzy location.

Leaflet

L.circle() natively accepts a radius in meters and renders a geographic circle; no need to generate polygon geometry.

MapLibre GL JS

MapLibre has no native geographic circle: you must generate a polygon approximation (e.g., 64-sided) from center and radius.

MapTiler SDK

Same polygon-based circle approach as MapLibre; the circle must be generated as GeoJSON geometry.

Which Library to Use?

auto_awesome

Build Maps with AI

Generate code like these examples using mapping library skills in your IDE.