Skip to main content

Roaming Geofence Subscription

Roaming Geofence Header Animation

Hivekit makes it easy to subscribe to realtime feeds for objects within specific regions, e.g., taxis in a certain part of town or first responders within a given radius around an accident location. But these regions don't need to be static - they can also move around.

tip

A region within a map that you want to get updates for is referred to as a "geofence". If this region moves around, it becomes a "roaming geofence".

Why you probably need this:

If you're building an app with a non-trivial number of objects moving on a map, e.g., a global shipment or aircraft tracker, you'll likely overwhelm your user's browser with location updates and map marker rendering.

To avoid this, it's good practice to limit the number of incoming updates to what's actually displayed on the user's screen. This can be achieved by specifying the user's viewport as a rectangular geofence in your subscription and updating it whenever the user pans or zooms.

But there are also other uses for this, including:

  • location-aware apps where users can discover shops and restaurants around them while walking the city streets.
  • coordination systems for police officers allowing them to see which colleagues with a given capability are currently nearby
  • dynamic logistics, showing collection and drop-off points around a moving delivery vehicle

How to implement roaming geofence subscriptions with Hivekit

To get a realtime feed for objects in a realm, you create a regular subscription:

const realm = await client.realm.get('my-realm');
const subscription = await realm.object.subscribe({
// you can use attribute filter to limit results
// based on properties in the object's data
attributes: ['type="deliveryRider"'],
// you can specify a circle, rectangle or polygon
shape: {
// circle with center at
cx: 13.3870811, //lon
cy: 52.528093, //lat
r: 500 // radius in m
}
});
subscription.on('update', objects => {
//map of objectId to objectData
})

To update this subscription, you simply call .update(options) with new parameters. You can do this as often as you like:

subscription.update({
shape: {
west: 13.374289,
east: 13.422689,
north: 52.5369157,
south: 52.513941
}
})

To limit updates to the current viewport on a map, you will want to listen to this viewport changing. For e.g. Google Maps, this would look as follows:

var mapSubscriptionUpdateScheduled = false;

map.addListener('bounds_changed', () => {
// this event fires for every frame the user pans or zooms. We don't want to
// update our subscription this frequently, so let's throttle it to max twice a second
if (!mapSubscriptionUpdateScheduled) {
mapSubscriptionUpdateScheduled = true;
setTimeout(updateMapSubscription, 500);
}
});

function updateMapSubscription() {
mapSubscriptionUpdateScheduled = false;
mapSubscription.update({
// the shape data with north, east, south and west coordinates returned
// by google map's getBounds().toJSON() method happens to be the exact
// format that Hivekit can use to specify rectangles. For other map libraries
// you might need to do some translation
//
// please also note: bounds_changed first fires before the map is loaded,
// leading to map.getBounds() returning null. You might want to add a check
// for this or only start listening to this event once the map's tilesloaded
// event first occured
shape: map.getBounds().toJSON()
})
}

You can find the full example of the Google Maps Integration here.