Progressively load Google Map markers when map pans or zooms. Only fetch data within the viewport.

Custom Code

With over 6000 map markers, Google Maps performance can become slow and Firebase document reads can become expensive.

I currently force the user to select a geographic filter which is not a great user experience.

I'm planning to use marker clustering, thanks to Blupry, to improve map performance/experience but I'd also like to restrict how many markers are loaded from Firebase by loading markers progressively based on the viewport.

In a different post, Matthew Holdsworth shared some great tips. I've copied them in this new post so not to confuse the other post which is focused on a different map topic here: https://community.flutterflow.io/widgets-and-design/post/custom-markers-google-maps-2ILaICDkNXuD7CU?highlight=aBk9T5NczbOaoxC

Matthew Holdsworth said:



onCameraIdle Functionality

The onCameraIdle callback is called when the map camera stops moving and becomes idle. This is an ideal place to:

  • Update Markers Based on New Map Center: After the user pans or zooms the map, causing the visible region to change, you might want to update the markers based on this new viewpoint. For example, you could load new markers that have entered the viewport or remove markers that are no longer visible.

Copy

void _onCameraIdle() {
  _updateMarkers();
}

This method is particularly useful for applications that need to display a dynamic set of markers that changes as the user explores the map. It helps in optimizing performance by only showing markers in the current viewport and can be used to fetch and display new data relevant to the area the user is looking at.

Implementation Guide

To integrate these functionalities into your Flutter app:

  1. Define the Callbacks: Ensure your GoogleMap widget specifies callbacks for onMapCreated and onCameraIdle.

Copy

GoogleMap(
  onCameraIdle: _onCameraIdle,
  // other properties...
)
  1. Implement the Callback Functions: Define _onCameraIdle methods in your state class, incorporating the logic outlined above.

  2. Manage State Appropriately: When updating markers or the map's appearance, ensure you manage the widget's state correctly to reflect these changes in the UI. This might involve calling setState to rebuild the widget with new data.


This looks great!

I think I can set lat/lng filters for a Firebase query getting documents/markers that belong within new "viewport" using LatLngBounds and getSouthEast & getNorthWest or similar. https://developers.google.com/maps/documentation/javascript/reference/coordinates

My question is, is there a more efficient way to fetch the data? If I run a query based on the new map bounds every time the map moves, I'll be fetching a lot of the same documents/markers again. How do I write a firebase query that only fetches documents/markers that have entered the viewport? And how do I join these new documents/markers with the existing documents/markers that were previously loaded from Firebase because they were already in the viewport?

Alternately, should I query all 6000 markers from Firebase up front, but then progressively load into Google Maps based on the viewport?

Or is there another way to query and cache "tiles" of data at a time then progressively load into Goole maps based on the viewport?

Or, should I restrict zoom-out so that it's not possible to query more than a few hundred markers at once, and accept that markers a re-loaded when the use pans or zooms.

To make things more complicated - the user can also filter the markers shown based on a choice chip "keyword" selection. When the user selects a new keyword, I re-query from firebase again.

What strategy would you use to manage this?

What have you tried so far?
Did you check FlutterFlow's Documentation for this topic?
Yes
3
4 replies