简体   繁体   中英

Google Maps API v3 - Multiple points with animation

I am building a directory of members which as well as listing members either in order of name and distance from a town or city, will display on a map using the Google Maps API v3.

I've got it working almost how I want it, but I am concerned that it's a bit slow. I'm already loading it asynchronously, but there is an issue with the markers.

I want the map to load and then the markers to appear in a drop animation one by one in quick succession. At the moment there is a delay and they all drop together and sometimes they appear on the map and then drop which looks very odd.

I'm using a PHP foreach script (from a MYSQL database) to output the javascript array for the members- there can be anywhere between 10 and 400 markers on the map, but usually no more than 100 at one time.

For brevity I've only included 4 markers in the example below (which as I said before is outputted from a PHP foreach script):

<script>
var infowindow = null;
$(document).ready(function () { initialize();  });
function initialize() {
    var centerMap = new google.maps.LatLng(53.1,-2.2);
    var myOptions = {
        zoom: 9,
        center: centerMap,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scrollwheel: false
    }

    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    setMarkers(map, sites);
    infowindow = new google.maps.InfoWindow({
            content: "loading..."
        });
}

 var sites = [
 ['Joe Bloggs',52.1022,-2.1070,1,"Member &nbsp;<a href=\"#\">Joe Bloggs</a>"],                              
 ['Peter Pan',52.2022,-2.2070,1,"Member &nbsp;<a href=\"#\">Peter Pan</a>"],                                
 ['Andrew Andrewson',52.0322,-2.0170,1,"Member &nbsp;<a href=\"#\">Andrew Andrewson</a>"],                              
 ['Peter Peterson',52.0022,-2.0070,1,"Member &nbsp;<a href=\"#\">Peter Peterson</a>"],  
 ];

function setMarkers(map, markers) {
    for (var i = 0; i < markers.length; i++) {
        var sites = markers[i];
        var siteLatLng = new google.maps.LatLng(sites[1], sites[2]);
        var marker = new google.maps.Marker({
            position: siteLatLng,
            map: map,
            title: sites[0],
            zIndex: sites[3],
            html: sites[4],
            animation: google.maps.Animation.DROP
        });

        var contentString = "Some content";
        google.maps.event.addListener(marker, "click", function () {
            infowindow.setContent(this.html);
            infowindow.open(map, this);
        });
    }
}


  function loadScript() {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'https://maps.googleapis.com/maps/api/js?key=my-key-is-here&sensor=false&' +'callback=initialize';
    document.body.appendChild(script);
  }

  window.onload = loadScript;
</script>

How can I speed this up and get the markers to appear in a drop animation after the page loads?

TL,DR: link to demo

In my opinion, you will have to write custom animation functions to create something slick.

I played around with the out-of-the-box google.maps.Animation.DROP and various setTimeout settings and couldn't come up with satisfactory settings. The biggest obstacle seems to be that a handful of marker DROPs happening at once quickly degrades the animation smoothness, resulting in an ugly, choppy, messy rain of markers. It even crashed my IE7 :(

In other words, if you want a good-looking sequence of DROPs, the time delay between successive DROPs needs to be relatively large (100-200 milliseconds), and at 100 markers, that means waiting 10 to 20 seconds until the last marker drops. I think it's far too long to have the end user sit through this whole animation, but if the DROP delays are short, the map's animation does not look good. It's a balance between animation quality and loading speed.

One workaround could be adding a click listener to the map so that when triggered, the remaining undisplayed markers show immediately. I have not added this logic in my demo.

Here's the demo on JSFiddle . There are three variables to play around with, one controlling the number of markers, and the other two controlling the delay between marker DROPs. You may change these values, then click on > Run to view the changes.

Some notes:

  1. I sort the random list so that the markers drop from top to bottom. I think it looks better than the scattered rain of markers. You might also rewrite the sort function by distance, so that sites close to a predefined center DROP first.

  2. There is a self-executing anonymous function wrapping the timeout, so that new variable scopes are created for each marker.

If your page is taking long to load, one option you have is to load the Google Maps API asynchronously using a callback that may be defined as a parameter on the URL that loads the Google Maps JavaScript library:

<script>
window.onload = loadGoogleMaps;

function loadGoogleMaps() {
   var script = document.createElement("script");
   script.type = "text/javascript";
   script.src =    
     "http://maps.googleapis.com/maps/api/jssensor=false&callback=initialize";
   document.body.appendChild(script);
}

This will allow you to retain your existing initialize function, which will run after the Google Maps JavaScript library has fully loaded, but you will want to remove the call to initialize() that is currently within your $(document).ready so that it doesn't run twice.

You shouldn't be seeing a two step process where the marker is placed on the map, followed by the DROP animation. You may also want to look at how long the setMarkers function is taking to run, because if that is taking overly long to run, it could possible be the root cause of what you are describing.

Edit based on follow up Comment:

One thing that you can use in JavaScript if you would like to create all of your markers, but add a delay between each marker creation is the JavaScript setTimeout( function, delayInMilliseconds function. You will have to keep track of where you are in your marker array across calls, but it works will to divide the work into distinct units of work. Using setTimeout , you should be able to add a short delay between each marker drop, which should give you the effect your are trying to achieve.

To space the marker creation timewise you could use window.setTimeout(), for example:

//UNTESTED!!
            function setMarkers(map, markers) {
                   while (markers.length) {
                    var markerData = markers.shift();
                    window.setTimeout(function(){doSetMarker(markerData,map)},10);// 10 miliseconds. (play with this value).
                    }
                }

                function doSetMarker(markerData,map) {
                    var sites = markerData;
                    var siteLatLng = new google.maps.LatLng(parseFloat(sites[1]), parseFloat(sites[2]));
                    var marker = new google.maps.Marker({
                        position: siteLatLng,
                        map: map,
                        title: sites[0],
                        zIndex: sites[3],
                        html: sites[4],
                        animation: google.maps.Animation.DROP
                    });
                        var contentString = "Some content";
                        google.maps.event.addListener(marker, "click", function () {
                            infowindow.setContent(this.html);
                            infowindow.open(map, this);
                        });

                }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM