UPDATE May 20, 2011: Google made an API update in version 3.4 that noticeably improves the standard method for loading markers. The method shown in this tutorial still loads faster.
If you have ever tried cramming more than 100 markers onto a Google map you know how poor the performance becomes. The default Google marker functions are slow if you need to deal with a large number of markers. This tutorial shows you how to add 1,000 markers to a Google map very fast. The load time difference on my computer went from around 20 seconds down to right under 2 seconds.
This is not another marker cluster approach. Gabriel Svennerberg has an excllent article comparing various clustering methods. Nor is it a pre-rendered image layer. This tutorial is for situations where you need to show many markers (more than 100) on various zoom levels without it crashing your browser.
The problem is DOM calls are very expensive. Every time a marker is added to the map, a function searches the DOM looking for the point to manipulate (add the marker).
Before we get into the code, I will give you two links below to test the difference in speed. Both links open in new windows. Note: I am using a custom marker icon (Sabramedia fish) for the fast loading example.
- Slow (API V3.3): 1,000 markers loading on a Google map (Beware it takes a while.)
- Slow (API V3.4): 1,000 markers loading on a Google map
- Fast (API V3.4): 1,000 markers loading on a Google map
UPDATED: Using Firebug in FF 4.0.1 to profile the number of calls compares like this:
- Slow render (API V3.3) - 2,087,604 calls
- Slow render (API V3.4) - 589,323 calls
- Fast render (API V3.4) - 133,363 calls (about same in V3.3)
Google Maps API V3 is used. Google has officially deprecated V2. A knowledge of how Google's Overlay object works will benefit your understanding of this tutorial. Let's begin.
The following code sets the boundary box that the 1,000 markers are randomly added to. The South West corner (latitude, longitude) is Los Angeles, California and the North East corner is New Your, NY.
Now we get into the heart of the code. We will create an overlay class (function) here that will be called after the Google map object is initialized later. We will prototype Google's OverlayView methods in order to create our marker layer.
The onAdd() method is called when the map is initialized. Here the new marker layer we created previously is appended to Google map's pane 4. The marker layer is cleaned up in onRemove() when the map is destroyed or removed.
The draw() method is where the marker layer is initialized, then re-drawn on every zoom. This is where the performance happens. Let's go through it.
Lines 3-5. Line 3 is absolutely critical to understand. This is the current projection view. This will be used later to convert latitude and longitude coordinates into pixel left and top position. Line 4 identifies the current zoom level. Line 5 is where we create the node holder with DocumentFragment before we push it to the DOM view.
Line 7. Remember that this.markerLayer is a jQuery object set in the onAdd() method. Because draw() is called on state changes such as zoom it will be important to do some clean up each time. That is where we use the jQuery empty() to clean up the marker layer, otherwise we would have element buildup in that layer. Not the desired effect.
Lines 9-14. The for loop begins, we arbitrarily set a thousand loops. Line 11 sets a random latitude/longitude object via Google's LatLng( lat, lng ) method. This could be any data set you want to pass into the loop of course.
Line 16. This is where the projection object methods come in handy. The method fromLatLngToDivPixel(object:LatLng) takes a Google LatLng object and converts it into the x/y pixel coordinates of the current projection view.
Line 17-33. I like jQuery's chaining of methods. They look neat and clean when adding attributes and style to a DOM element such as a DIV tag; However, they are slow and noticeably so when working with many elements. Skip the chaining and simply create the element by appending strings in order to improve the speed. It saved me about 28,000 calls in this tutorial example.
Line 35-51. This code block is optional. I added to illustrate the flexibility with this approach. For zoom level 8 or closer a tool tip is shown above the marker icon.
Line 54. Here we append the HTML for the marker point to the fragment.
Set the default latitude/longitude position. I used the location of our office in Jasper, Indiana in this case. Initialize the map with desired options. Lastly apply the custom OverlayView that you just created.
After this code I added a simple jQuery UI dialog to the map. In this example the dialog just opens in the center. Bringing the marker to the map center and adjusting for the dialog is possible, but beyond the scope of this tutorial. Email me if you would like the code for this.