API на Google Maps: Създайте локатор на магазин

Днес се опитвам да направя локатор на магазини, използвайки 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 към onclick
  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='/bg" + 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" и т.н. Това противоречи на всичко, което знам за компютрите.


person Joseph Carrington    schedule 28.08.2009    source източник
comment
Малко несвързано, но наистина трябва да съхранявате геокодовете в базата данни, след като бъдат получени веднъж, тъй като това трябва да ускори приложението ви.   -  person wheresrhys    schedule 30.08.2009
comment
За да направя това, ще трябва да добавя кука в wordpress MU admin, за да изпълня javascript асинхронна xml заявка и да се уверя, че тази заявка е завършена ПРЕДИ потребителят да изпрати формуляра.   -  person Joseph Carrington    schedule 30.08.2009
comment
Вероятно ще е по-добре да използвате HTTP геокодера, за да съхранявате местоположенията във вашата база данни. code.google.com/apis/maps/documentation/geocoding/index. html   -  person Chris B    schedule 30.08.2009


Отговори (4)


Забравете за затварянето за момент. Можете да се потопите в тях, след като получите работещо приложение. Мисля, че вашата цел в този момент трябва да бъде просто да получите нещо, което постига това, което искате.

За мен изглежда, че единственото нещо, което ви липсва, е идеята за функция за обратно извикване . Например addElementToList ще бъде подаден като аргумент за обратно извикване към geocoder.getLocaitons. Начинът, по който работи е, че когато getLocations() приключи, той извиква addElementToList и предоставя резултата от getLocations() като аргумент на addElementToList. След това кодът за addElementToList ще добави местоположението на вашия магазин към картата като маркер и ще добави нов елемент към вашия html списък с името или адреса на магазина или каквото и да е друго.

Разгледайте тази публикация в блога за прост пример с използване на обратно извикване: Представяне на геокодирането на Google Услуга.

Последната част, центрирана върху конкретен магазин, може да се направи (както предложихте) със слушатели на събития. Можете да настроите слушател за кликвания върху маркерите, а също и за кликвания върху вашия списък. Когато добавите маркер, можете също да добавите слушател на събития към него. Би било хубаво, ако можете да зададете един слушател за всички маркери на картата, но не съм достатъчно запознат с API на Google, за да знам дали това е възможно.

person Derek Swingley    schedule 29.08.2009

Какъв е вашият източник на тази информация? placeMarker със сигурност не бие звънец. Референцията за API на Google Карти (допълнена с примери!) е достъпна на адрес http://code.google.com/apis/maps/documentation/reference.html

person Rushyo    schedule 28.08.2009
comment
няколко функции са по мой собствен дизайн, placeMarker е просто по-лесен начин да кажа function placeMarker(response) { if (!response || response.Status.code != 200) { } else { place = response.Placemark[0]; point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]); marker = new GMarker(point); map.addOverlay(marker); } - person Joseph Carrington; 29.08.2009

Въз основа на вашия коментар към отговора на @Rushyo - изглежда, че знаете достатъчно за Javascript и API на Google Maps, за да конструирате тези функции. Малко съм объркан какво търсите.

Бих предложил обаче първо да добавите координати за ширина/дължина към вашата база данни. Не трябва да геокодирате адресите при всяко зареждане на картата.

Актуализация: В отговор на вашия коментар по-долу, ето кода, който посочихте - заедно с функцията addAddressToMap(), извикана от Geocoder. Той създава маркер за всеки адрес и го добавя към масива 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 поради асинхронния характер на Geocoder. Не забравяйте, че вашата getLocations() функция ще изпраща заявки за всяко местоположение в масива, преди да получи обратно каквито и да било отговори.

person Chris B    schedule 28.08.2009
comment
Предполагам, че просто се надявах на някакъв план, в който мога да попълня подробностите. Мога повече или по-малко да създавам функциите, но не мога да ги накарам да работят една с друга. Знам, че това са функциите, които обикновено са включени във всички локатори на магазини, които съм виждал, но просто не знам как трябва да се появят една спрямо друга. Не мога да разбера как да предавам данни напред и назад между функцията на javascript, тя не работи като в php, който е езикът, с който съм значително по-удобен. - person Joseph Carrington; 29.08.2009
comment
По принцип току-що се ударих в стената на познанието си и не мога да измисля как да се измъкна от този проблем. И, разбира се, функционалността трябваше да стане преди дни и дни. - person Joseph Carrington; 29.08.2009
comment
Например ` 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(адрес, addAddressToMap); }` така че имам функция, която взема адрес и го превръща в latLng обект, след което поставя маркер под този latLng, но как мога някога да препратя този обект отново? Има някаква основна част от javascript, която не разбирам - person Joseph Carrington; 29.08.2009
comment
И така, има ли някакъв начин да се върне latLng на геокодера и да се използва за различна функция, без тази функция да е обратно извикване на геокодера? Трябва да вмъкна URL адреса на магазин в адресите infoWindow, но няма начин да предам дата на функцията за обратно извикване на геокодера - person Joseph Carrington; 30.08.2009

Създавам нов отговор, тъй като другият ми отговор става объркан.

За да получите правилно затваряне, ще трябва да създадете отделна функция, за да направите заявка за геокодер. Следният код ще ви позволи да присвоите желания текст на infoWindow към всеки маркер.

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 Maps вижте тези въпроси:

person Chris B    schedule 30.08.2009