javascript 从 Google Maps (V3) 外部打开特定标记的 infoWindow

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4904549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 15:18:14  来源:igfitidea点击:

Open infoWindow of specific marker from outside Google Maps (V3)

javascriptdatabasegoogle-mapsgoogle-maps-markersinfowindow

提问by chocolata

I can't seem to get my head around this problem:

我似乎无法解决这个问题:

I've got a map with (a lot of) markers (companies) that come from a generated XML file. Below the map, I want to show a (non-JavaScript-generated) list of all the companies that are displayed on the map. When I would click a company in the list, the map would pan to that specific marker and open an infoWindow. The thing is that I want the map and the list to be two separate things...

我有一个带有(很多)标记(公司)的地图,这些标记来自生成的 XML 文件。在地图下方,我想显示地图上显示的所有公司的(非 JavaScript 生成的)列表。当我单击列表中的一家公司时,地图将平移到该特定标记并打开一个信息窗口。问题是我希望地图和列表是两个独立的东西......

What would be the right way to tackle this problem? Thanks! Important is that all markerinfo is dynamic...

解决这个问题的正确方法是什么?谢谢!重要的是所有标记信息都是动态的...

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() {}

Following the suggestions by Michal, I've tried the following, but am encountering two problems: my console tells me markers[index].getPosition is not a functionand the first item in my list shows to be undefined. Can you please help?

按照 Michal 的建议,我尝试了以下操作,但遇到了两个问题:我的控制台告诉我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(){
}

采纳答案by Michal

You are on the right track. You just need to create a separate global array for your Marker objects and push all created markers to this array. When you write out all your company data to html include a call with the index of the marker executed on click. Below is an example code. I used JSON as my data structure to hold company info instead of XML.

你在正确的轨道上。你只需要为你的 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> 

Ok I added another solution for you - uising your code. This one uses your bindInfWindow function to bind the DOM (HTML) click event to open info window and scroll to marker. Please note that because you are loading companies dynamically the divs (or some other tags) that hold their names and ids must exist in the DOM BEFORE you start binding events to it - so the first function you need to execute is the one that renders companies HTML (not the map init). Please note I have not tested this one as I do not have your data..

好的,我为您添加了另一个解决方案 - 使用您的代码。这个使用您的 bindInfWindow 函数来绑定 DOM (HTML) 单击事件以打开信息窗口并滚动到标记。请注意,因为您正在动态加载公司,所以在您开始将事件绑定到 DOM 之前,保存其名称和 ID 的 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> 

回答by feruz

since i cannot remove this answer, I decided to add some notes!

由于我无法删除此答案,因此我决定添加一些注释!

if your xml format is similar to this: http://www.w3schools.com/dom/books.xml

如果您的 xml 格式类似于:http: //www.w3schools.com/dom/books.xml

you may access authornodeValue with following lines.

您可以使用以下几行访问作者nodeValue。

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

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

hope it helps someone :)

希望它可以帮助某人:)