具有多个标记的Google地图自动中心

时间:2017-11-29 17:59:51

标签: javascript jquery google-maps maps google-maps-markers

我创建了一个地图,将我的搜索结果显示为地图上的标记,它几乎完美无缺,但是自动中心/缩放功能不能正常工作。地图地址或动态,所以我不能硬编码特定的坐标。

我使用了之前question和其他代码中的一些代码来使用 bounds 来尝试从2个标记中获取坐标并找到中心,但无论我做什么它只是不能正常工作。

这是我正在使用的代码---

<!--- SEARCH MAP --->
<div id="map_wrapper">
    <div id="map_canvas" class="mapping"></div>
</div>

<?php function getCoordinates($address){
$address = str_replace(" ", "+", $address); // replace all the white space with "+" sign to match with google search pattern
$url = "https://maps.googleapis.com/maps/api/geocode/json?address=$address&key=TOKEN_KEY";
$response = file_get_contents($url);
$json = json_decode($response,TRUE); //generate array object from the response from the web
return ($json['results'][0]['geometry']['location']['lat'].",".$json['results'][0]['geometry']['location']['lng']);
} ?>

<script type="text/javascript">

<?php
$locations = array();
//$location_query = new WP_Query( array(
//'posts_per_page' => 100
// ) );

echo "//markers: 100\n";
echo "var locations = [";
$comma = "";
//while ( $location_query->have_posts() ) {
//$location_query->the_post();

while (have_posts()) {
the_post();

$add = get_post_meta(get_the_ID(), 'address', true);
$property_pin = get_post_meta(get_the_ID(), 'pincode', true);
$terms = wp_get_post_terms(get_the_ID(), 'city');

if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
     foreach ( $terms as $term ) {
if ($term->parent == 0) {
     $addy = getCoordinates($add, $term->name);  
     }
  }

}

$title = str_replace("'", "\'", get_the_title());
echo $comma . "['" . $title . "', " . $addy . ", " . get_the_id() . "]";  
$comma = ", ";
}
echo "];\n\n";

//info content
echo "var theinfo = [";
$comma2 = "";

while (have_posts()) {
the_post();

$add = get_post_meta(get_the_ID(), 'address', true);
$property_price = get_post_meta(get_the_ID(),'price',true);
$terms = wp_get_post_terms(get_the_ID(), 'city');

if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
     foreach ( $terms as $term ) {
if ($term->parent == 0) { //check for parent terms only
     $tcity = $term->name;    
     }
  }

}

$title = str_replace("'", "\'", get_the_title());
$link = get_the_id();
$linkto = '<a href="/property/'.$link.'/">'.$title.'</a>';
$class = 'class="mapmarkers"';
echo $comma2 . "['<div ".$class."><h3>" . $linkto . "</h3><h4>" . $tcity . "</h4><p>$" . $property_price ."</p></div>']";  
$comma2 = ", ";
} 
echo "];\n\n";

?>

 var map;
   var bounds = new google.maps.LatLngBounds();
    var mapOptions = {
center: new google.maps.LatLng(0, 0),
zoom: 0,
minZoom: 5, 
maxZoom: 15,
        mapTypeId: 'roadmap'
    };

    // Display a map on the page
    map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
    map.setTilt(45);

// Info Window Content
    var infoWindowContent = theinfo;

 // Display multiple markers on a map
    var infoWindow = new google.maps.InfoWindow(), marker, i;

    // Loop through our array of markers & place each one on the map 
    for( i = 0; i < locations.length; i++ ) {
        var position = new google.maps.LatLng(locations[i][1], locations[i][2]);
        marker = new google.maps.Marker({
            position: position,
            map: map,
            title: locations[i][0]
        });
//bounds.extend(position);
bounds.extend(marker.getPosition());

        // Allow each marker to have an info window    
        google.maps.event.addListener(marker, 'click', (function(marker, i) {
            return function() {
                infoWindow.setContent(infoWindowContent[i][0]);
                infoWindow.open(map, marker);
            }
        })(marker, i));

// Automatically center the map fitting all markers on the screen
 map.fitBounds(bounds);
 map.panToBounds(bounds); 
}

  // Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
    var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
       this.setZoom(8);
    google.maps.event.removeListener(boundsListener);
   });
</script>

使用我的代码,地图渲染如此--- WRONG

但我需要它更像这样--- CORRECT

示例仅使用2个标记,但实际数量和位置将是动态的。我该如何解决这个问题?

更新

我的坐标var locations = [['1460 Broadway', 40.7551055,-73.9862093, 2299], ['246 W 18th St', 40.741807,-74.0000351, 2114]];

3 个答案:

答案 0 :(得分:2)

TL; DR

根据给定的样本位置, 和你分享的代码, 我无法重现问题: 正确调整地图视图以使位置可见。

现在怎么办?

  • 验证程序中的位置数据。

    • lat-lon值是否在预期范围内? - &GT;纬度约为40.7,离线约为-74
    • 纬度值是否在位置数组中的顺序正确? - &GT; Lat位于索引1(如locations[i][1]中),lon位于索引2(如locations[i][2]中所示)
  • 确认您的实际代码与发布的代码完全匹配 - &gt;如果发布的代码中缺少一些重要信息,我们可能会调试错误的东西......

  • 将您的问题更新为Minimal, Complete, and Verifiable example

  • 有关调试过程的更多详细信息,请参见下文,以及该程序的JavaScript部分的其他一些改进建议。

根据您发布的代码和示例locations, 我创建了这个最小的例子。 与您的代码唯一重要的区别是这部分, 注册一个回调来初始化地图:

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

在您发布的代码中,您无法看到初始化地图的方式。 在任何情况下,如果您初始化不正确, 症状应该不是截图中的地图,但根本没有地图, 所以我想这不是你的问题。 但我建议您验证初始化。

请亲自尝试此示例,并在问题中确认是否可以使用它重现问题。 如果你不能(我怀疑), 那么为了帮助你, 如果你根据这个做出Minimal, Complete, and Verifiable example,那将是最好的。

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map_canvas {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="map_canvas"></div>
    <script>
function initMap() {
  var locations = [
    ['1460 Broadway', 40.7551055,-73.9862093, 2299],
    ['246 W 18th St', 40.741807,-74.0000351, 2114]
  ];
  var map;
  var bounds = new google.maps.LatLngBounds();
  var mapOptions = {
    center: new google.maps.LatLng(0, 0),
    zoom: 0,
    minZoom: 5, 
    maxZoom: 15,
    mapTypeId: 'roadmap'
  };

  // Display a map on the page
  map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
  map.setTilt(45);

  // Info Window Content
  var infoWindowContent = locations;  // suitable dummy value

  // Display multiple markers on a map
  var infoWindow = new google.maps.InfoWindow(), marker, i, position;

  // Loop through our array of markers & place each one on the map 
  for (i = 0; i < locations.length; i++) {
    position = new google.maps.LatLng(locations[i][1], locations[i][2]);
    marker = new google.maps.Marker({
      position: position,
      map: map,
      title: locations[i][0]
    });
    bounds.extend(position);

    // Allow each marker to have an info window    
    google.maps.event.addListener(marker, 'click', (function(marker, i) {
      return function() {
        infoWindow.setContent(infoWindowContent[i][0]);
        infoWindow.open(map, marker);
      }
    })(marker, i));

    // Automatically center the map fitting all markers on the screen
    map.fitBounds(bounds);
    map.panToBounds(bounds); 
  }

  // Override our map zoom level once our fitBounds function runs (Make sure it only runs once)
  var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
    this.setZoom(8);
    google.maps.event.removeListener(boundsListener);
  });
}
    </script>
    <script src="https://maps.googleapis.com/maps/api/js?callback=initMap"
            async defer></script>
  </body>
</html>

这就是输出的样子:

output from original code

它不是很好,但是点位于可见的中心, 与我们在帖子中看到的完全不同。 我真的认为你错过了一些重要的细节。

此时,可以进行一些简单的改进:

  • 缩放级别8不适合这些点,让我们放弃它
    • 因为这是boundsListener的唯一工作,所以也放弃了
    • 请注意boundsListener从一开始就显得毫无意义,因为您已拨打map.fitBoundsmap.panToBounds
  • 不是为每个点调用map.fitBoundsmap.panToBounds,而是将其移出循环,并在将所有点添加到bounds之后调用它

基于以上建议,代码的JavaScript部分变为:

function initMap() {
  var locations = [
    ['1460 Broadway', 40.7551055,-73.9862093, 2299],
    ['246 W 18th St', 40.741807,-74.0000351, 2114]
  ];
  var map;
  var bounds = new google.maps.LatLngBounds();
  var mapOptions = {
    center: new google.maps.LatLng(0, 0),
    zoom: 0,
    minZoom: 5, 
    maxZoom: 15,
    mapTypeId: 'roadmap'
  };

  // Display a map on the page
  map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
  map.setTilt(45);

  // Info Window Content
  var infoWindowContent = locations;  // suitable dummy value

  // Display multiple markers on a map
  var infoWindow = new google.maps.InfoWindow(), marker, i, position;

  // Loop through our array of markers & place each one on the map 
  for (i = 0; i < locations.length; i++) {
    position = new google.maps.LatLng(locations[i][1], locations[i][2]);
    marker = new google.maps.Marker({
      position: position,
      map: map,
      title: locations[i][0]
    });
    bounds.extend(position);

    // Allow each marker to have an info window    
    google.maps.event.addListener(marker, 'click', (function(marker, i) {
      return function() {
        infoWindow.setContent(infoWindowContent[i][0]);
        infoWindow.open(map, marker);
      }
    })(marker, i));
  }

  // Automatically center the map fitting all markers on the screen
  map.fitBounds(bounds);
  map.panToBounds(bounds); 
}

输出变为:

after minor refactoring

就我迄今为止提供的信息而言,这是我所能得到的。 而且我没有看到问题。

我希望以上内容有助于您的调试, 或者基于此,您将发布Minimal, Complete, and Verifiable example,以帮助其他人找到您的问题。

答案 1 :(得分:0)

我想出了问题,最外面的地图容器(未显示有问题)被设置为在页面加载时不显示任何内容,因此我可以使用单击函数在地图视图和帖子的常规列表视图之间切换。

所以我有 -

    <div id="map_view" style="display:none;">
    <div id="map_wrapper">
    <div id="map_canvas" class="mapping"></div>
    </div>
<script> blah blah </script>
</div>

如果我取消display none,它似乎在页面加载时正确加载。理想情况下,我不希望首先显示地图,但这似乎是迄今为止唯一的解决方案。

答案 2 :(得分:0)

可能这可以帮助一些人。 如果您需要在标记周围添加波纹,则可以执行此类操作。您可以根据您的要求为所有或部分标记添加纹波。

    <!DOCTYPE html>
    <html> 
    <head> 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> 
   <title>Google Maps Multiple Markers</title> 
  <script src="http://maps.google.com/maps/api/js?sensor=false" 
          type="text/javascript"></script>
</head> 
<body>
  <div id="map" style="width: 1000px; height: 500px;"></div>

   <script type="text/javascript">
     var locations = [
     ['Saudi Arabia',23.885942, 45.079162   , 6],
      ['United Arab Emirates', 23.424076, 53.847818, 4],
      ['Bahrain',25.930414  ,50.637772  , 5],
      ['Iraq',  33.223191,  43.679291   , 3],
      ['Kuwait',29.31166,   47.481766   , 2],     
      ['Qatar',25.354826,   51.183884   , 1]
    ];

    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 10,
      center: new google.maps.LatLng(23.885942, 45.079162),
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    var infowindow = new google.maps.InfoWindow();

    var marker, i;

    var icon = {
                url: "Ripple.svg", // url of ripple svg image
                scaledSize: new google.maps.Size(200, 200), // scaled size
                origin: new google.maps.Point(0,0), // origin
                anchor: new google.maps.Point(100,100) // anchor
            };        

  for (i = 0; i < locations.length; i++) {   
      marker = new google.maps.Marker({

        position: new google.maps.LatLng(locations[i][1], locations[i][2]),
        map: map, 
         icon: icon,
            optimized: false
      });

       google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
          infowindow.setContent(locations[i][0]);
          infowindow.open(map, marker);
        }
      })(marker, i));
      }
for (i = 0; i < locations.length; i++) { 
      marker = new google.maps.Marker({
        position: new google.maps.LatLng(locations[i][1], locations[i][2]), 
        map: map
      });

      google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
          infowindow.setContent(locations[i][0]);
          infowindow.open(map, marker);
        }
      })(marker, i));
    }


  </script>
</body>
</html>

showing ripple around marker[![][2]] 3