Circles / Radius Overlays
Use this guide when you need translucent metric circles on a MapVXMap — for
example to visualize a geofence or proximity-notification radius around a location. The radius is
expressed in meters, so the circle keeps its geographic size at every zoom level.
Setup
Create a map first, then keep its MapVXMap instance around for future circle
operations:
import { initializeSDK, type CircleConfig, type LatLng, type MapVXMap } from "@mapvx/web-js"
const sdk = initializeSDK("<YOUR_API_KEY>")
const mapContainer = document.getElementById("map") as HTMLElement
const map: MapVXMap = sdk.createMap(mapContainer, {
center: { lat: 4.666918, lng: -74.053065 },
zoom: 17,
})Create a circle
The only required fields in CircleConfig are coordinate and
radiusMeters. Styling defaults to the MapVX brand blue with a translucent fill:
const center: LatLng = {
lat: 4.666918,
lng: -74.053065,
}
const circle: CircleConfig = {
id: "geofence-entrance",
coordinate: center,
radiusMeters: 150,
}
const circleId = map.addCircle(circle)Every styling property can be overridden per circle:
map.addCircle({
id: "geofence-warehouse",
coordinate: { lat: 4.6675, lng: -74.0535 },
radiusMeters: 75,
fillColor: "#e53935",
fillOpacity: 0.2,
strokeColor: "#e53935",
strokeWidth: 3,
strokeOpacity: 0.8,
})Validate before adding
Before adding a circle configuration, you can pre-validate it with isValidCircleConfig:
import { isValidCircleConfig } from "@mapvx/web-js"
const userInput = {
/* ... */
}
if (isValidCircleConfig(userInput)) {
map.addCircle(userInput)
} else {
console.error("Invalid circle configuration")
}This is useful when accepting circle data from users or APIs.
Update a circle
Use updateCircle to fully replace the configuration of an existing circle. The payload must
include the same id; omitted styling fields fall back to their defaults:
const result = map.updateCircle({
id: circleId,
coordinate: center,
radiusMeters: 300,
fillOpacity: 0.25,
})
if (result === null) {
console.error("Circle not found")
}updateCircle returns the circle id on success, or null if no circle matches.
Move or resize without rebuilding
When only the center or radius changes (e.g. while the user drags a location or adjusts a radius
slider), updateCirclePosition keeps the styling untouched:
const success = map.updateCirclePosition(circleId, { lat: 4.6672, lng: -74.0528 })
// Optionally pass a new radius in meters as the third argument
if (success) {
map.updateCirclePosition(circleId, { lat: 4.6672, lng: -74.0528 }, 250)
} else {
console.error("Circle not found")
}updateCirclePosition returns true on success, false if the circle doesn’t exist.
Update styling without recreating geometry
Use updateCircleStyle to efficiently update only the appearance (colors, opacity, stroke width)
without rebuilding the geometric polygon:
// Brighten the circle on hover
const success = map.updateCircleStyle(circleId, {
fillOpacity: 0.3,
strokeOpacity: 0.9,
})This is much faster than updateCircle when geometry stays the same.
Inspect and retrieve circles
Check existence and retrieve circle data:
// Check if a circle exists before operating on it
if (map.hasCircle(circleId)) {
const circle = map.getCircle(circleId)
console.log(`Circle radius: ${circle?.radiusMeters}m`)
}
// Get all circles on the map
const allCircles = map.getCircles()
console.log(`Map has ${allCircles.length} circles`)
// Find circles in a region
const circles = map.getCircles()
const nearbyCircles = circles.filter(
(c) => Math.hypot(c.coordinate.lat - myLat, c.coordinate.lng - myLng) < 0.01
)Hide and show circles
Hidden circles keep their identity and configuration. Unlike markers, a hidden circle stays hidden across floor changes and map restyles until you show it again:
// Hide a circle
if (map.hideCircle(circleId)) {
console.log("Circle hidden")
} else {
console.error("Circle not found")
}
// Show it again later
if (map.showCircle(circleId)) {
console.log("Circle visible again")
}Both hideCircle and showCircle return true on success, false if the circle doesn’t exist.
Remove one circle or all of them
map.removeCircle(circleId)
map.removeAllCircles()Indoor circles
A circle with a floorId is shown only while that floor is displayed, with the same semantics as
MarkerConfig.floorId. Circles without a floorId are shown in
outdoor contexts:
map.addCircle({
id: "geofence-food-court",
coordinate: { lat: 4.6669, lng: -74.0531 },
radiusMeters: 40,
floorId: "level-2",
})Circles automatically survive floor transitions and map style changes — there is no need to re-add
them after updateFloor or a parent place change.
Render order (z-placement)
By default circles render above every basemap geometry layer — including indoor floor-plate and
building polygons — and below the labels that follow them, so a circle is never hidden by the map
itself. Use renderOrder when you need a different placement:
// Default: above floor plates and buildings, below labels
map.addCircle({ coordinate, radiusMeters: 150 })
// Legacy placement: below the first label layer of the style.
// On indoor styles, floor polygons may paint over the circle.
map.addCircle({ coordinate, radiusMeters: 150, renderOrder: "belowLabels" })
// Above everything, including labels
map.addCircle({ coordinate, radiusMeters: 150, renderOrder: "top" })The placement is re-asserted automatically after floor changes and map style swaps, so circles keep
their z-order without any consumer-side moveLayer calls.
When to use other examples
- Go to Basic Markers when you need point markers with icons or labels instead of area overlays.
- Go to Floor Management for parent places and floor transitions that drive indoor circle visibility.