API Карт Google: создание локатора магазина - PullRequest
3 голосов
/ 29 августа 2009

Сегодня я пытаюсь создать локатор магазина, используя API Google Maps. Локатор магазина должен быть настроен так: две области, одна с картой, содержащей все магазины в данной области (измеренной в выбираемом радиусе от центральной точки), и одна область со списком всех магазинов на карте, их информацией и, конечно же, ссылкой на их сайт. Когда человек нажимает на название магазина в списке магазинов, он центрируется на магазине на карте и открывает информационное окно над маркером магазина.

У меня есть переменная javascript, которой я старался присвоить некоторые данные json из сценария php (который выбирает эти данные на лету из базы данных)

locations = [{"siteurl":"http:\/\/localhost.localdomain\/5","address":"260 Test St","city":"Brooklyn","state":"New York","zip_code":"11206"},{"siteurl":"http:\/\/localhost.localdomain\/4","address":"3709 Testing St.","city":"Austin","state":"Texas","zip_code":"78705"}]; 

Теперь я знаю, что мне нужно запустить 5 различных функций, перечисленных ниже с их очевидным использованием:

  1. geocoder.getLocations: используется для преобразовать адресные данные (из JSON объект) в широту и долготу объект данных
  2. addElementToList: Используется для добавления информации об адресе в список магазинов, и связать centerOnStore функция для нажатия
  3. centerOnStore при щелчке элемента списка магазина в области списка этот функциональный центр располагается в магазине, который был выбран в области карты. Эта функция также открывает информационное окно над центром в хранилище.
  4. placeMarker функция для размещения маркера на карте, вызываемая, когда геокодер возвращает объекты latitudeLongitude
  5. eventListener это связано каким-то образом при нажатии на элемент списка, и это дополнительно центрирует карту в соответствующем магазине

Ну, я бы вышел из своей лиги. Я только сейчас узнаю о закрытиях JavaScript, и я думаю, что они могут быть необходимы, но я не совсем понимаю их. Мне нужно найти какой-то способ привести все эти функции в рабочее состояние, передавая информацию друг другу и обратно, и создать локатор магазина

.


Вот что у меня есть, но с этим что-то очень не так.

    var map = null;
    var geocoder = null;
    var locations = null;
    var center_on = null;
    var zoom_level = null;
    var markerList = [];

    function initialize()
    {
            if(GBrowserIsCompatible())
            {
                    // Assign vars
                    map = new GMap2(document.getElementById("map_canvas"));
                    geocoder = new GClientGeocoder();
                    locations = <?php echo(json_encode($my_vars['locations'])); ?>;
                    center_on = "<?php echo($my_vars['center_on']); ?>";
                    zoom_level = <?php echo($my_vars['zoom_level']); ?>;
                    var currentLocation = 0;

                    geocoder.getLatLng(center_on, function(myPoint)
                    {
                            map.setCenter(myPoint, zoom_level);
                    });
                    map.setUIToDefault();


                    var list = document.getElementById('center_list');

                    for(var i = 0; i < locations.length; i++)
                    {
                            var address = locations[i]['address'] + ', ' + locations[i]['city'] + ' ' + locations[i]['state'] + ', ' + locations[i]['zip_code'];
                            geocoder.getLocations(address, addAddressToMap);
                    }

            }




            function addAddressToMap(response) {

                    if (!response || response.Status.code != 200) {
                            currentLocation++;
                    } else {
                    var place = response.Placemark[0];
                    var point = new GLatLng(place.Point.coordinates[1],
                            place.Point.coordinates[0]);
                    marker = new GMarker(point);
                    GEvent.addListener(marker, 'click', function(){
                            this.openInfoWindowHtml("<strong>" + place.address + "</strong><br /><a href='" + locations[currentLocation]['siteurl'] + "'>" + locations[currentLocation]['siteurl'] + "</a>");
                    });
                    map.setCenter(point, 13);
                    markerList.push(marker);
                    map.addOverlay(marker);
                    li = document.createElement('li');

                    li.innerHTML = "<strong>" + place.address + "</strong>";
                    li.setAttribute('onclick', 'center_on_center(' + place.Point.coordinates[1] + ',' + place.Point.coordinates[0] + ')');
                    li.setAttribute('id', 'center_');
                    li.style.fontSize = '1.4em';
                    document.getElementById('center_list').appendChild(li);
                    // alert(currentLocation) here says 0,0,0,0
                    currentLocation++;
                    // alert(currentLocation) here says 1,2,3,4
                    }
            }
    }

Прошу прощения за стену кода. Я не могу больше думать. Я понятия не имел, что это будет так сложно. Понятия не имею.

если я предупреждаю currentLocation в строке перед тем, как увеличивать ее, это всегда 0. Но если я предупреждаю ее в строке после того, как увеличиваю ее, это '1,2,3,4' и т. Д. Это идет вразрез со всем, что я знаю о компьютерах.

Ответы [ 4 ]

1 голос
/ 29 августа 2009

Забудьте о замыканиях на мгновение. Вы можете погрузиться в них, как только вы получите рабочее приложение. Я думаю, что ваша цель на данный момент должна состоять в том, чтобы просто получить то, что выполняет то, что вы хотите.

Мне кажется, что единственное, что вам не хватает - это идея функции обратного вызова . Например, addElementToList будет передан в качестве аргумента обратного вызова для geocoder.getLocaitons . Это работает так: когда getLocations () завершает работу, он вызывает addElementToList и предоставляет результат getLocations () в качестве аргумента addElementToList. Затем код для addElementToList добавит местоположение вашего магазина на карту в качестве маркера и добавит новый элемент в ваш HTML-список с именем или адресом магазина или чем-то еще.

Взгляните на этот пост в блоге для простого примера использования обратного вызова: Представляем сервис геокодирования Google .

Последняя часть, сосредоточенная на конкретном хранилище, может быть выполнена (как вы предложили) с помощью прослушивателей событий. Вы можете настроить прослушиватель для кликов по маркерам, а также для кликов в вашем списке. Когда вы добавляете маркер , вы также можете добавить в него прослушиватель событий . Было бы неплохо, если бы вы могли установить один слушатель для всех маркеров на карте, но я недостаточно знаком с API Google, чтобы знать, возможно ли это.

0 голосов
/ 30 августа 2009

Я создаю новый ответ, так как мой другой ответ становится грязным.

Чтобы получить правильное закрытие, вам нужно создать отдельную функцию для запроса геокодера. Следующий код позволит вам назначить желаемый текст информационного окна для каждого маркера.

for(var i = 0; i < locations.length; i++) {
    var address = locations[i]['address'] + ', ' + locations[i]['city'] + ' ' + locations[i]['state'] + ', ' + locations[i]['zip_code'];
    var text = locations[i]['address']; // or whatever you want the text to be
    getLocation(address, text);
}

...

function getLocation(address, text) {
    geocoder.getLocations(address, function(response) {
        var place = response.Placemark[0];
        var point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
        marker = new GMarker(point);
        marker.bindInfoWindowHtml(text); // note that if you want to use GEvent.addListener() instead - you'll need to create another function to get proper closure
        map.addOverlay(marker);
    });
}

Подробнее о закрытии на картах Google см. Следующие вопросы:

0 голосов
/ 29 августа 2009

Исходя из вашего комментария к ответу @ Rushyo, кажется, что вы достаточно знаете о Javascript и API Карт Google, чтобы сконструировать эти функции. Я немного смущен тем, что вы ищете.

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

Обновление: В ответ на ваш комментарий ниже приведен код, на который вы ссылались - наряду с функцией addAddressToMap(), вызываемой геокодером. Создает маркер для каждого адреса и добавляет его в массив markerList. Затем вы можете получить доступ к маркерам в этом массиве позже, поскольку мы инициализировали его вне области действия функции addAddressToMap().

for(var i = 0; i < locations.length; i++) { 
    var address = locations[i]['address'] + ', ' + locations[i]['city'] + ' ' + locations[i]['state'] + ', ' + locations[i]['zip_code'];
    geocoder.getLocations(address, addAddressToMap); 
}

var markerList = new array();

function addAddressToMap(response) {
    if (!response || response.Status.code != 200) {
        alert("\"" + address + "\" not found");
  } else {
      place = response.Placemark[0];
      point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
      marker = new GMarker(point);
      markerList.push(marker);
      map.addOverlay(marker);
  }
}

Обновление 2: В ответ на код, который вы разместили в своем вопросе выше, вы, вероятно, получаете случайные числа в currentLocation из-за асинхронного характера геокодера. Помните, что ваша функция getLocations() будет отправлять запросы для каждого местоположения в массиве, прежде чем получит какие-либо ответы обратно.

0 голосов
/ 29 августа 2009

Каков ваш источник этой информации? PlaceMarker, конечно, не звонит в колокол. Справочник по API Карт Google (с примерами!) Доступен по адресу http://code.google.com/apis/maps/documentation/reference.html

...