Открыть информационное окно определенного маркера вне Карт Google (версия 3)

Я не могу понять эту проблему:

У меня есть карта с (множеством) маркеров (компаний), которые взяты из сгенерированного файла XML. Под картой я хочу показать (сгенерированный не JavaScript) список всех компаний, которые отображаются на карте. Когда я щелкал компанию в списке, карта перемещалась к этому конкретному маркеру и открывала информационное окно. Дело в том, что я хочу, чтобы карта и список были двумя разными вещами...

Каким будет правильный способ решения этой проблемы? Спасибо! Важно то, что вся информация о маркерах является динамической...

function initialize_member_map(lang) {
  var map = new google.maps.Map(document.getElementById("large-map-canvas"), {
    center: new google.maps.LatLng(50.85034, 4.35171),
    zoom: 13,
    mapTypeId: 'roadmap'
  });
  var infoWindow = new google.maps.InfoWindow;

  downloadUrl("/ajax/member-xml-output.php", function(data) {
  var xml = data.responseXML;
  var markers = xml.documentElement.getElementsByTagName("marker");
  var bounds = new google.maps.LatLngBounds();
  for (var i = 0; i < markers.length; i++) {
    var company = markers[i].getAttribute("company");
    var address = markers[i].getAttribute("address");
    var type = markers[i].getAttribute("type");
    var uid = markers[i].getAttribute("uid"); // Primary key of company table in MySQL
    var point = new google.maps.LatLng(
        parseFloat(markers[i].getAttribute("lat")),
        parseFloat(markers[i].getAttribute("lng")));
    var html = "<b>" + company + "</b> <br/>" + address;
    bounds.extend(point);    
    var marker = new google.maps.Marker({
      map: map,
      position: point,
      uid: uid // Some experiments, wanted to use this to target specific markers...
    });
    bindInfoWindow(marker, map, infoWindow, html); 
  }        
  map.setCenter(bounds.getCenter());
  map.fitBounds(bounds); 
});
}

function bindInfoWindow(marker, map, infoWindow, html) {
  google.maps.event.addListener(marker, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
  });
}

function downloadUrl(url, callback) {
  var request = window.ActiveXObject ?
    new ActiveXObject('Microsoft.XMLHTTP') :
    new XMLHttpRequest;

  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      request.onreadystatechange = doNothing;
      callback(request, request.status);
    } 
  };

  request.open('GET', url, true);
  request.send(null);
}
function doNothing() {}

Следуя предложениям Михала, я попробовал следующее, но столкнулся с двумя проблемами: моя консоль сообщает мне markers[index].getPosition is not a function, а первый элемент в моем списке отображается как undefined. Не могли бы вы помочь?

//JavaScript Document
var map;
var markers = new Array();
var company_list;
function initialize_member_map(lang) {
  map = new google.maps.Map(document.getElementById("large-map-canvas"), {
    center: new google.maps.LatLng(50.85034, 4.35171),
    zoom: 13,
    mapTypeId: 'roadmap'
  });
  var infoWindow = new google.maps.InfoWindow;

  // Change this depending on the name of your PHP file
  downloadUrl("/ajax/member-xml-output.php?country=BE", function(data) {
    var xml = data.responseXML;
    markers = xml.documentElement.getElementsByTagName("marker");
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0; i < markers.length; i++) {
      var company = markers[i].getAttribute("company");
      var address = markers[i].getAttribute("address");
      var type = markers[i].getAttribute("type");
      var uid = markers[i].getAttribute("uid");
      var point = new google.maps.LatLng(
          parseFloat(markers[i].getAttribute("lat")),
          parseFloat(markers[i].getAttribute("lng")));
      var html = "<b>" + company + "</b> <br/>" + address;
      bounds.extend(point); 
      var marker = new google.maps.Marker({
        map: map,
        position: point,
        uid: uid
      });
      bindInfoWindow(marker, map, infoWindow, html); 
      company_list += "<div onclick=scrollToMarker(" + i + ")>"+company+"</div>";
    }       
    map.setCenter(bounds.getCenter());
    map.fitBounds(bounds); 
    //display company data in html
    document.getElementById("company_list").innerHTML = company_list;
  });

}

function scrollToMarker(index) {
    map.panTo(markers[index].getPosition());
}

function bindInfoWindow(marker, map, infoWindow, html) {
  google.maps.event.addListener(marker, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
  });
}

function downloadUrl(url, callback) {
  var request = window.ActiveXObject ?
      new ActiveXObject('Microsoft.XMLHTTP') :
      new XMLHttpRequest;

  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      request.onreadystatechange = doNothing;
      callback(request, request.status);
    }
  };

  request.open('GET', url, true);
  request.send(null);
}
function doNothing(){
}

person chocolata    schedule 05.02.2011    source источник


Ответы (2)


Ты на правильном пути. Вам просто нужно создать отдельный глобальный массив для ваших объектов Marker и поместить все созданные маркеры в этот массив. Когда вы записываете все данные вашей компании в html, включите вызов с индексом маркера, выполняемого по клику. Ниже приведен пример кода. Я использовал JSON в качестве структуры данных для хранения информации о компании вместо XML.

<html> 
<head> 
    <meta name="viewport" content="initial-scale=1.0, user-scalable=yes" /> 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
    <title>Google Maps Scroll to Marker</title> 

    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> 

</head> 
<body onload="initialize()"> 

    <div id="map_canvas" style="width: 900px;height: 600px;"></div> 
    <div id="companies"></div>
    <script type="text/javascript"> 
        var map;
        //JSON of company data - equivalent of your XML 
        companies = {
            "data": [
            {
                "name": "Company 1",
                "lat": 42.166,
                "lng": -87.848 
            }, 
            {
                "name": "Company 2",
                "lat": 41.8358,
                "lng": -87.7128 
            },
            {
                "name": "Company 3",
                "lat": 41.463, 

                "lng": -88.870 
            },
            {"name":"Company 4",
            "lat":41.809, "lng":-87.790}		
            ]
        }
        //we will use this to store google map Marker objects 
        var markers=new Array();
        function initialize() {
            var chicago = new google.maps.LatLng(41.875696,-87.624207);
            var myOptions = {
                zoom: 9,
                center: chicago,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            }
            map = new google.maps.Map(document.getElementById("map_canvas"),
                myOptions);
            listCompanies();
        }		 

        function listCompanies() {
            html = ""
        //loop through all companies
        for (i=0;i<companies.data.length;i++) {
        //get the maker postion
        lat  = companies.data[i].lat
        lng =  companies.data[i].lng

        //add google maps marker
        marker = new google.maps.Marker({
            map:map,
            position: new google.maps.LatLng(lat,lng),
            title: companies.data[i].name
        })
        markers.push(marker);
        html += "<div onclick=scrollToMarker(" + i + ")>"+companies.data[i].name+"</div>";
        }
        //display company data in html
        document.getElementById("companies").innerHTML =html;
        }

        function scrollToMarker(index) {
            map.panTo(markers[index].getPosition());
        }
</script>

</body> 
</html> 

Хорошо, я добавил для вас еще одно решение - использование вашего кода. Этот использует вашу функцию bindInfWindow для привязки события клика DOM (HTML), чтобы открыть информационное окно и прокрутить до маркера. Обратите внимание, что, поскольку вы загружаете компании динамически, элементы div (или некоторые другие теги), которые содержат их имена и идентификаторы, должны существовать в DOM ДО того, как вы начнете привязывать к нему события, поэтому первая функция, которую вам нужно выполнить, — это та, которая отображает компании. HTML (не инициализация карты). Обратите внимание, что я не проверял это, так как у меня нет ваших данных.

//you must write out company divs first

<body onload="showCompanies()">



<script>
//JavaScript Document
var map;
//this is your text data
var markers = new Array();


//you need to create your company list first as we will be binding dom events to it so it must exist before marekrs are initialized
function showCompanies() {
 downloadUrl("/ajax/member-xml-output.php?country=BE", function(data) {
    var xml = data.responseXML;
    markers = xml.documentElement.getElementsByTagName("marker");

    for (var i = 0; i < markers.length; i++) {
      var company = markers[i].getAttribute("company");

      markerId = "id_"+i;

      company_list += "<div id="+markerId+">"+company+"</div>";
    }       

    //display company data in html
    document.getElementById("company_list").innerHTML = company_list;

    //now you are ready to initialize map
    initialize_member_map("lang")
  });
}

function initialize_member_map(lang) {
  map = new google.maps.Map(document.getElementById("large-map-canvas"), {
    center: new google.maps.LatLng(50.85034, 4.35171),
    zoom: 13,
    mapTypeId: 'roadmap'
  });




    var xml = data.responseXML;

    var bounds = new google.maps.LatLngBounds();
    //your company data was read in and is ready to be mapped
    for (var i = 0; i < markers.length; i++) {
      var infoWindow = new google.maps.InfoWindow;
      var company = markers[i].getAttribute("company");
      var address = markers[i].getAttribute("address");
      var type = markers[i].getAttribute("type");
      var uid = markers[i].getAttribute("uid");
      var point = new google.maps.LatLng(
          parseFloat(markers[i].getAttribute("lat")),
          parseFloat(markers[i].getAttribute("lng")));
      var html = "<b>" + company + "</b> <br/>" + address;
      bounds.extend(point); 
      var marker = new google.maps.Marker({
        map: map,
        position: point,
        uid: uid
      });
      //add the new marker object to the gMarkers array

      markerId = "id_"+i;
      bindInfoWindow(marker, map, infoWindow, html,markerId); 

    }       
    map.setCenter(bounds.getCenter());
    map.fitBounds(bounds); 


}

function scrollToMarker(index) {
    map.panTo(markers[index].getPosition());
}

function bindInfoWindow(marker, map, infoWindow, html, markerId) {
  google.maps.event.addListener(marker, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
  });
  //bind onlcick events to the div or other object in html
  markerObj =  document.getElementById(markerId);
  //you can create DOM event listeners for the map
  google.maps.event.addDomListener(markerObj, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
    map.panTo(marker.getPosition());
  });

}

function downloadUrl(url, callback) {
  var request = window.ActiveXObject ?
      new ActiveXObject('Microsoft.XMLHTTP') :
      new XMLHttpRequest;

  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      request.onreadystatechange = doNothing;
      callback(request, request.status);
    }
  };

  request.open('GET', url, true);
  request.send(null);
}
function doNothing(){
}

</script> 
person Michal    schedule 05.02.2011
comment
Спасибо, Михал. Я попробовал ваши предложения, но застрял на двух вещах, описанных в вопросе выше. Не могли бы вы помочь? Спасибо! - person chocolata; 06.02.2011
comment
Вы пытаетесь получить доступ к свойствам маркера в массиве, в котором вы храните свои xml (текстовые данные), а не объекты маркера. Извините, в моем сценарии я назвал свои маркеры массива объектов, поэтому возникла путаница. Все, что вам нужно сделать, это определить другой массив для хранения объекта маркера Google Maps - назовите его gMarkers и поместите в него каждый маркер по мере их создания. - person Michal; 06.02.2011
comment
После этого вам нужно изменить ссылку маркеров на gMarkers в scrollToMarker(). - person Michal; 06.02.2011
comment
Я также отредактировал свое решение, чтобы показать вам, как связывать события DOM непосредственно в вашей функции bindInfoWindow(), так что это альтернативное решение для первого. - person Michal; 06.02.2011
comment
Спасибо, Михал. Все это работает! Ты настоящий профи! Просто из любопытства, как я смогу открыть infoWindows, используя ваше первое решение? - person chocolata; 06.02.2011
comment
В scrollToMarker() вы должны создать новое информационное окно и указать в содержимом соответствующее название компании (companies.data[index].name) - person Michal; 06.02.2011
comment
Спасибо, Михал! Это тоже работает! Теперь я собираюсь сделать некоторые настройки (первый элемент списка все еще не определен, и я хочу изменить уровни масштабирования при нажатии в списке). Еще раз спасибо за помощь. - person chocolata; 07.02.2011

так как я не могу удалить этот ответ, я решил добавить несколько заметок!

если ваш формат xml подобен этому: http://www.w3schools.com/dom/books.xml

вы можете получить доступ к author nodeValue с помощью следующих строк.

markers = xml.documentElement.getElementsByTagName("book");

for (var i = 0; i < markers.length; i++) {
  authors = markers[i].getElementsByTagName('author')[0].innerHTML;
}

надеюсь кому-то поможет :)

person feruz    schedule 06.10.2013