Google Maps V3: How To Quickly Add Many Markers Without Killing The Map

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 principal here is making use of DOM DocumentFragments. I first learned about DocumentFragments from John Resig. John's little discovery has majorly increased the speed of our JavaScript applications at Sabramedia.

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.

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)

Download the full code for fast marker loading here.

Code Explained

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.

 

Firebug HTML view of the Google map structure and overlay location. Overlay layer pane 4 is highlighted.

 

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.

Comments

  • Angel

    December 19, 2010

    Awesome tutorial, this helped me out with a project I'm currently working on.

    To take it one step further though, if you wanted to dynamically add new markers to the map through some sort of UI modal how would you set this functionality up? Would you just push the newly created marker onto the array of markers and redraw the map overlay? Or could you add a function to just append a new 'map-point' div to the DOM?

    Thanks again for the walkthrough.

  • Nick Johnson

    December 28, 2010

    @Angel. Two things you need to add a marker dynamically are, 1) The current projection and 2) The custom marker layer in the DOM.

    In this tutorial you can access the custom marker layer via the OverlayMap.markerLayer. The projection can be set either in a global variable for the current state, or you can set it in this.projection so it can be accessed via OverlayMap.projection.

    Keep in mind that this tutorial randomly sets the lat/lng of the points in the draw() method. You would need to keep an external data set of the lat/lng's, including any markers dynamically added after initialization, to refer to every time the draw() method is called e.g. on zoom. I hope this helps.

  • Mark

    April 20, 2011

    I have same prolems here, What can i do?

  • Jeremy

    May 17, 2011

    This is a very cool method of drawing the markers. However, I noticed that the "slow" page isn't really much slower than the fast page. I would guess that something changed in the google code to accelerate this.

    Would your technique still be useful in a case where there are 1000 markers all based on different images?

  • Craig

    May 20, 2011

    Nice tutorial. I noticed the same as Jeremy. Both are pretty fast.

  • Nick Johnson

    May 20, 2011

    @Jeremy, @Craig
    Thanks guys for bringing this to my attention. It appears that Google did make a significant improvement in version 3.4. I updated the tutorial to make mention of this.

    @Jeremy
    Regarding the images, this method would be better than the standard method, but this is an entirely separate issue. This tutorial shows an improved method for rendering the actual code markup. If you are loading 1,000 different images, then you might want use a clustering or MarkerManager approach. You can see these at the Svennerberg link in the article above or checkout this Google article.


  • dungnguyen

    July 31, 2011

    I benmarked 2 examples : yours and one with google suggestion (create markers normally by call their contructors) and the result is that google is 20 times faster! (i'm using firefox 5)

  • Robert

    August 24, 2011

    Panning the map around w/ your custom marker is noticeably slower and choppy compared with the Slow V3.4 method in Chrome and FF.

  • Vaishakh

    September 1, 2011

    I have around 20,000 markers how do I go about , should I server side clustering or client side ?

  • Bowral Boy

    October 25, 2011

    Great tutorial! The fragment method looks like an interesting approach to minimising marker display overheads. Excited to give it a try!

  • Aldo Lavin

    February 29, 2012

    How can I implement some different map layers witch depend of checkboxes?

    I would like to activate/deactivate layers independiently.

    Thanks.

  • Aldo Lavin

    February 29, 2012

    How can I implement some different map layers witch depend of checkboxes?

    I would like to activate/deactivate layers independiently.

    Thanks.

  • Fernando Ott

    May 10, 2012

    Great Tutorial Nick!
    Really solve my problems with markers.

    But one problem that I detected was the map.fitBounds(...) method.

    This method just didn't work anymore with this approach. You know what could be?

    Thanks

  • seti

    July 20, 2012

    Hi Nick Johnson, thanks so much for this great artical.

    Can you please send the jqurey UI dialog code to me?

    seti

  • seti

    July 20, 2012

    My eamil addr:

    greatseti@hotmail.com

  • Zachary

    October 19, 2012

    This is fantastic! I'd love to see your code.

  • sam

    March 20, 2013

    This is very nice post.

  • Jaime Yule Jacobson

    May 20, 2013

    awesome post!

  • Abhay Yadav

    June 10, 2013

    Nice tutorial.

  • Tommy Brask

    June 11, 2013

    Find "How To Quickly Add Many Markers Without Killing The Map" and try to convert it for my application because I need a fast system to show information big amount of markers.
    I'm relatively new at JQuery and trying to learn more and now I have problem how to write texts in the box who appear when clicking a marker, in the example only ID is showing. I find your tutorial very helpful and informative.

  • Laurence Blake

    June 19, 2013

    Maybe i'm doing something wrong, but the other two approaches run much quicker for me than your approach.

  • Mahen

    July 1, 2013

    Nice post. Really helpful to play with G Maps for novice Developers. Cool !
    Few Useful comments to run through.

    Recent V3 examples by Google are helpful : https://developers.google.com/maps/documentation/javascript/overlays#AddingOverlays

  • Ricky

    July 30, 2013

    Pls speak English

  • H5bak

    January 20, 2014

    OMG!!!
    This is a very awesome post.
    Thanks.

  • Rohit Verma

    July 2, 2014

    hi nick,
    this is great tutorial , this helped me lot

    I just need to know how to attach events on markers ?

  • August 8, 2014

    Hi I want to load markers in after map loaded and button is clicked event how can i do that? plz help

  • Joao Conceicao

    September 16, 2014

    Hi, nice approach. Can you send me the code?

    Thanks!

  • anil

    April 7, 2015

    How top add different icon for 20000 locations

  • Mengyu

    April 23, 2015

    nice post! I've learnt a lot from this tuto. But when i opened these three links in the beginning of article, the approach presented is the slowest one. Another reader Laurence Blake has the same result. Maybe I do something wrong? Anybody else test with these three examples?

  • Ricardo Santana

    June 10, 2015

    First I would like to congratulate for your article has been of great ajusda for the project I'm imprementando in the company in which work.
    However I am with the following section difficulty, I am unable to update the markers in the map of events "dragend" and Zoom!
    You podeira guide me about it?

    graciously
    Ricardo Santana

  • November 19, 2015

    ooo

  • Stefan Maier

    November 21, 2015

    Hi, first of all: thanks a lot for your effort! I also tried all 3 links. But apparently the same issue happens as Mengyu described. Actually the first link (fast one) made my firefox unusable (froze) for at least 30 seconds. Guess it's related to some change on the google side, cause this article was written in 2012. Do you have any information on that?

    Cheers!

  • Pankaj S.

    March 23, 2016

    Firstly thanks for making this example. But this is not working with dynamic location and run time loading xml. I am creating xml for marker location as per google doc. Its working but taking too much time. And when using this example. XML is not loaded. How to fix this ?

    Basically i am creating map dynamically on click. Every time different location marker.

  • April 27, 2017

    Brilliant. I've been trying to find a way to do this for days. Thanks

  • Anson

    January 17, 2018

    This example saved me lots of time. Thanks you so much!

  • Lee

    April 20, 2020

    This is nice. How would I implement clustering with zoom in on clicking a cluster?

  • Lee

    April 24, 2020

    I checked out the clustering link you posted in the comments above. That brings me back to the original problem though because running "new google.maps.Marker..." thousands of times was the bottle neck. Is there a better approach? Also, I also noticed as someone else commented that fitbounds no longer works on the map. How would I do that.

Add Comment