6

I want to load 80,000 markers on google map, I have functions, setMarkers() and createMarker(). It is taking very long time to load. How can I speed the page?

code is below:

function initialize() {
    //markers details are coming from json file
    setMarkers(map, markers);
}
function setMarkers(map, locations) {
    //from location object, all the variables get values
    //infobox code
    //loop starts for all markers
    createMarker( arguments );
    //loop end for all markers
}
function createMarker( arguments ) {
    //marker creation code
}

Also is it possible to increase speed using google map purchased API key?

Eleena
  • 87
  • 1
  • 4
  • 7
    How can you speed up the page? Don't load 80,000 markers on it. Seriously. That is an in-human amount of data to process. You could try putting some geolocation logic in to it so that only the ~100 markers closest to the maps current focal point get loaded. – Rory McCrossan Apr 26 '16 at 10:03
  • I want that only the markers which is located in visible area are loaded first, asynchronous loading. But I am not getting how to do it because of functions. – Eleena Apr 26 '16 at 10:08
  • 3
    .filter() the list of 80,000 down to ones that are > minLat and < maxLat shown, do the same for lon, then draw only those markers each time the map view changes. – dandavis Apr 26 '16 at 10:10
  • @dandavis, can you give me the details how to use filter() in my functions? – Eleena Apr 26 '16 at 10:32
  • lower the digits in lat,lon to 6 floating numbers if you don't care 10 cm accuracy. it will save space in the json data. I read about this suggestion in geojson standard. – nurp Aug 13 '23 at 12:56

2 Answers2

11

Here are some ways to optimize your markers:

  1. Grid-based Clustering. Grid-based clustering works by dividing the map into squares of a certain size (the size changes at each zoom) and then grouping the markers into each grid square.
  2. Distance-based Clustering. Distance-based clustering is similar to grid-based clustering, except instead of creating clusters of fixed square bounds, clusters are created based on the distance between the marker and a cluster centroid.
  3. Viewport Marker Management. A viewport marker manager works by getting the current bounds of the map that is visible to the user, then — based on the map's bounds — a query is sent to the server to get all the markers that lie within the bounds. As the user pans/zooms the map subsequent requests are sent to the server to get the new markers. All markers that are no longer in view are generally removed to improve map performance.
  4. Fusion Tables. By using FusionTablesLayer from the JavaScript API, a large number of points can be displayed on the map. Because rendering is performed on Google servers rather than within your users' browsers, performance is improved dramatically.
  5. markerCluster.The MarkerClusterer is a client side utility library that applies grid-based clustering to a collection of markers. It works by iterating though the markers in the collection that you wish to cluster and adding each one into the closest cluster if it is within in a minimum square pixel bounds.
  6. MarkerManager. The MarkerManager allows you to more discretely define what markers you want visible at different zoom levels. The MarkerManager has a more involved setup than the MarkerClusterer, but it does allow for more customization of what and where it displays.

Note: Don't forget that markers have an option optimized, but will not be true if you use animated gifs or PNG, so if you use that type of file think about it twice.

Thomas Karachristos
  • 3,237
  • 18
  • 22
3

I had a similar problem on a project before.

Zoom management

Depending on the zoom used by the user I had to show way too much markers. So I had to find a way to limit the numbers of markers displayed depending on the zoom level that was used.

I used the markerManager plugin (http://google-maps-utility-library-v3.googlecode.com/svn/tags/markermanager/1.0/docs/examples.html).

function initialize() {
    var mapOptions = {
        scaleControl: true,
        center: new google.maps.LatLng(50, 3),
        zoom: 17,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    mgr = new MarkerManager(map);
};

Then when you add a new marker you use the manager to set a minimum and maximum zoomLevel where the marker is visible. The marker won't be displayed if not in the zoom range.

function add_marker(lat, lng, zoomMin, zoomMax, img, path, camPos) {
    var marker = new google.maps.Marker({
    position: new google.maps.LatLng(lat, lng),
    icon: "file:///" + path + "/images/" + img + ".png"
    });

    google.maps.event.addListener(marker, 'click', function () {
    form1.jsCamPos = camPos;
    form1.changePosition();
    });

    mgr.addMarker(marker, zoomMin, zoomMax);
}

Thanks to that you can set all your detailled marker at the max zoom level and for higher zoom levels instead of displaying all the markers add some more marker to suggest your user to zoom in in order to see the detailled markers.

This will greatly improve your application reactivity.

Markers map bounds filtering

Another way to do would be to load asynchronously the markers depending on the bounds of the map.

You can for example add a listener to the bounds_changed event which is fired each time the map is moved, then you get the new bounds and call a webService which will give you all the markers inside the new bounds.

google.maps.event.addListener(map, 'bounds_changed', function () {
    var lat0 = map.getBounds().getNorthEast().lat();
    var lng0 = map.getBounds().getNorthEast().lng();
    var lat1 = map.getBounds().getSouthWest().lat();
    var lng1 = map.getBounds().getSouthWest().lng();

    var parameters = "{'lat0':'" + lat0 + "','lng0':'" + lng0 + "','lat1':'" + lat1 + "','lng1':'" + lng1 + "'}";

/*
The webService should reply something like this :
[
 {"lat":50.5215,"lng":2.515,"title":"marker1"},
 {"lat":50.5126,"lng":2.5165,"title":"marker2"},
 {"lat":50.5127,"lng":2.54564,"title":"marker3"}
];
*/

    $.ajax({
        type: "POST",
        url: webMethod,
        data: parameters,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(msg) {
            $.each (msg, function (idx) {
                console.log (msg[idx].lat);
                console.log (msg[idx].lng);

                var marker = new google.maps.Marker({
                    position: new google.maps.LatLng(msg[idx].lat, msg[idx].lng),
                    title: msg[idx].title,
                    map:map
                });
            });
        },
        error: function(e){
            alert('error!');
        }
    });
});
Nicolas
  • 127
  • 1
  • 10
  • I don't want to let user zoom in to view the markers. I want that new markers create and user can see the markers if pan is moved. – Eleena Apr 26 '16 at 10:50
  • Then you can listen for the viewport change event bounds_changed get the bounds of the map and the retrieve all the markers that are inside and load them (I will edit my answer to illustrate that). Anyway I do think that the zoom is still a problem you will need to handle. If the map is greatly zoomed out at the eath scale then your 80 000 markers will be in the bounds of the map. – Nicolas Apr 26 '16 at 11:03
  • Can you give me the code with my above two functions? – Eleena Apr 26 '16 at 11:14
  • 1
    I could if you post the code of your setMarker and createMarker function. Also where are your markers coming from ? Do you have a webservice behind providing the markers lat, lng and icon / text (I assumed so) ? – Nicolas Apr 26 '16 at 11:22
  • nicolas is right. If you want code provide some code, otherwise the question is very general and you will receive very general answer . – Thomas Karachristos Apr 26 '16 at 12:19
  • Thank you for your effort! I added the code. – Eleena Apr 27 '16 at 06:13
  • If i understand correctly you read a remote json file which contains your markers. A little profiling would help to see where time goes. Can you try to measure the time taken by the loading of your json file and then the setMarker function. (To measure time see : http://stackoverflow.com/questions/313893/how-to-measure-time-taken-by-a-function-to-execute). Also count the complete time it takes to render the page (perhaps it is only the rendering of the page after the calls to google map api which takes long time). If the json loading is quick you could store it in memory and filter it. – Nicolas Apr 27 '16 at 06:56
  • json file is not on remote server. It is on root of the same server. setMarker() function takes 26.794s time. – Eleena Apr 27 '16 at 08:54