Google Maps API: Setting up callbacks for adding markers/polyline

本小妞迷上赌 提交于 2019-12-19 10:21:18

问题


I'm trying to add a polyline to the Google Map generated. The coordinates for the polyline are taken from a JSON file on my web server using jQuery (getJSON function). However, I'm having trouble with callbacks. I've defined three functions in a separate JavaScript file, and these are:

function initMap(callback) {

    map = new google.maps.Map(document.getElementById('map-canvas'), {
        center: {lat: 34.397, lng: 150.644},
        scrollwheel: false,
        zoom: 2
    });

    callback();
}

.

function setPath(callback) {

   $.getJSON('./expOneActivityData.json',

       function (data) {

           //Some looping contstruct to navigate through my JSON file.   
       }
   })

   callback();
};

.

function addPath() {

    var trekLine = new google.maps.Polyline({

        path: expeditionCoordinates,
        geodisc: true,
        stokeColor: '#FF0000',
        strokeOpacity: 1.0,
        strokeWeight: 2
    });

    trekLine.setMap(map);

}

expeditionCoordinates being an array, each element being an object with latitude and longitude property. This is declared as a global variable, with value initialisation happening in setPath()'s loop.

In my HTML file, I have:

<script src="https://maps.googleapis.com/maps/api/js?key=myKey&callback=initMap">

When I try to replace initMap with initMap(setPath(addPath)) in the script tag, I get a 400 Bad request from Google. Ofcourse having just "callback=initMap" in the script tag gives a:

TypeError: callback is not a function

occuring at line with callback() in initMap's definition.

So how can I pass a function to googleapis, where the function itself also has callbacks? (My looping construct is fine btw). I tried adding 'defer' to the googleapi script tag, and also to the one linking to my JavaScript file. I removed all the callbacks stuff, and only excecuted the loop. I hoped the expeditionCoordinates array would finish initialisation before the googleapi script tag is excecuted, though that didnt work either (map still loads, just with no polyline).

I'm fairly new to Javascript and it's asynchronous nature, though I do understand how they work and have been succesfully working with them at a basic level for a week or so.

(Which actually leads me to a side question. Up until now I've only worked with one callback. I would expect something like:

initMap(setPath)

to work as setPath does not have () attached when its definition is passed as a parameter, and hence is not excecuting immediately. Though adding a set of brackets to setPath, as it also takes a callback (addPath), would mean it does get excecuted immediately?)


回答1:


There are several issues with the provided example:

1) When loading the Google Maps API, callback parameter accepts callback function name where the function itself should have the following signature:

function initMap() {
   //...
}

where

<script src="https://maps.googleapis.com/maps/api/js?key=myKey&callback=initMap" async defer></script>

Only parameter-less callback function could be specified this way.

2) Since jQuery.getJSON() is async by default and you are passing function callback, the implementation of setPath function should like this:

function setPath(callback) {
    $.getJSON('./expOneActivityData.json',
        function (data) {
            callback(data);
        }
    );
};

Working example

function initMap() {
    var map = new google.maps.Map(document.getElementById('map-canvas'), {
        center: { lat: 34.397, lng: 150.644 },
        scrollwheel: false,
        zoom: 2
    });

    setPath(function(data) {
        addPath(map,data);
    });
}

function setPath(callback) {
    $.getJSON('https://gist.githubusercontent.com/vgrem/91ba4d694157169b112c/raw/5bdd81c6f5bdfa5ba2d0ca8d5494129b329399d8/expOneActivityData.json',
        function (data) {
            callback(data);
        }
    );
};


function addPath(map,expeditionCoordinates) {
    var trekLine = new google.maps.Polyline({
        path: expeditionCoordinates,
        geodisc: true,
        stokeColor: '#FF0000',
        strokeOpacity: 1.0,
        strokeWeight: 2
    });
    trekLine.setMap(map);
}
html, body {
    height: 100%;
    margin: 0;
    padding: 0;
}

#map-canvas {
    height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&callback=initMap"
            async defer></script>



回答2:


You can't pass parameters in the callback parameter of the Google Maps Javascript API v3 script include.

This won't work:

<script src="https://maps.googleapis.com/maps/api/js?key=myKey&callback=initMap(setPath(addPath))"></script>

as you discovered. Something like this should:

function initMap() {
    map = new google.maps.Map(document.getElementById('map-canvas'), {
        center: {lat: 34.397, lng: 150.644},
        scrollwheel: false,
        zoom: 2
    });
    setPath(addPath));
}

function setPath(callback) {
  $.getJSON('./expOneActivityData.json',
    function(data) {
      // Some looping contstruct to navigate through my JSON file.
      // create the expeditionCoordinates array
      callback(expeditionCoordinates);
    }
  );
};

function addPath(expeditionCoordinates) {
  var trekLine = new google.maps.Polyline({
    path: expeditionCoordinates,
    geodisc: true,
    stokeColor: '#FF0000',
    strokeOpacity: 1.0,
    strokeWeight: 2
  });

  trekLine.setMap(map);
}

Using this to asynchronously load the API:

<script src="https://maps.googleapis.com/maps/api/js?key=myKey&callback=initMap" async defer></script>



回答3:


You can, however, add a one-time event listener to mimic sending a callback.

var map;

function initMap(mapId, latLong, callback) {
    //...

    map = new google.maps.Map(document.getElementById(mapId), {
        zoom: 16,
        center: latlng
    });


    // This is what you're interested in...
    if ($.isFunction(callback)) {
        google.maps.event.addListenerOnce(map, 'tilesloaded', callback);
    }
}

That keeps the callback out of the script src URL and your code procedural, though adding the event listener after you're already cut the new Map code loose seems a little odd.

And note that though its logic is a little more linear, it might not load quite as fast as doing async "the right way" as in Vadim's answer.



来源:https://stackoverflow.com/questions/34379664/google-maps-api-setting-up-callbacks-for-adding-markers-polyline

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!