Google Maps API: настройка обратных вызовов для добавления маркеров / ломаной линии

Я пытаюсь добавить ломаную линию к созданной карте Google. Координаты ломаной линии берутся из файла JSON на моем веб-сервере с помощью jQuery (функция getJSON). Однако у меня проблемы с обратными вызовами. Я определил три функции в отдельном файле JavaScript, а именно:

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 - это массив, каждый элемент которого является объектом со свойством latitude и longitude. Это объявлено как глобальная переменная, при этом инициализация значения происходит в цикле setPath ().

В моем HTML-файле у меня есть:

<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

происходит в строке с callback () в определении initMap.

Итак, как я могу передать функцию в googleapis, где сама функция также имеет обратные вызовы? (Моя конструкция цикла в порядке, кстати). Я попытался добавить defer к тегу скрипта googleapi, а также к тому, который ссылается на мой файл JavaScript. Я удалил все обратные вызовы и выполнил только цикл. Я надеялся, что массив ExpeditionCoordinates завершит инициализацию до того, как тег скрипта googleapi будет исключен, хотя это тоже не сработало (карта все еще загружается, только без ломаной линии).

Я новичок в Javascript и его асинхронном характере, хотя я понимаю, как они работают, и успешно работал с ними на базовом уровне в течение недели или около того.

(Что на самом деле приводит меня к побочному вопросу. До сих пор я работал только с одним обратным вызовом. Я ожидал чего-то вроде:

initMap(setPath)

для работы, поскольку setPath не имеет прикрепленного (), когда его определение передается в качестве параметра, и, следовательно, не выполняется немедленно. Хотя добавление набора скобок в setPath, поскольку он также требует обратного вызова (addPath), будет означать, что он будет немедленно исключен?)


person luks    schedule 20.12.2015    source источник
comment
Функция обратного вызова (initMap) для асинхронного загрузчика не может принимать никаких аргументов, это указатель на функцию.   -  person geocodezip    schedule 20.12.2015


Ответы (3)


В приведенном примере есть несколько проблем:

1) При загрузке API Карт Google параметр callback принимает обратный вызов имя функции, где сама функция должна иметь следующую сигнатуру:

function initMap() {
   //...
}

куда

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

Таким образом можно указать только функцию обратного вызова без параметров.

2) Поскольку jQuery.getJSON() по умолчанию async, и вы передаете обратный вызов функции, реализация setPath функции должно понравиться это:

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

Рабочий пример

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>

person Vadim Gremyachev    schedule 21.12.2015

Вы не можете передавать параметры в параметре callback сценария Google Maps Javascript API v3 include.

Это не сработает:

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

как вы обнаружили. Примерно так должно:

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);
}

Используя это для асинхронной загрузки API:

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

Однако вы можете добавить одноразовый прослушиватель событий, чтобы имитировать отправку обратного вызова.

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);
    }
}

Это позволяет исключить обратный вызов src URL-адреса сценария и процедурного кода вашего кода, хотя добавление прослушивателя событий после того, как вы уже отключили new Map код, кажется немного странным.

И обратите внимание, что, хотя его логика немного более линейна, она может загружаться не так быстро, как выполнение async «правильным способом», как в ответе Вадима.

person ruffin    schedule 12.03.2018