【问题标题】:Auto-center map with multiple markers in Google Maps API v3在 Google Maps API v3 中使用多个标记自动居中地图
【发布时间】:2013-03-21 03:22:38
【问题描述】:

这是我用来显示带有 3 个图钉/标记的地图:

<script>
  function initialize() {
    var locations = [
      ['DESCRIPTION', 41.926979, 12.517385, 3],
      ['DESCRIPTION', 41.914873, 12.506486, 2],
      ['DESCRIPTION', 41.918574, 12.507201, 1]
    ];

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

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

    var 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));
    }
  }

  function loadScript() {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&' + 'callback=initialize';
    document.body.appendChild(script);
  }

  window.onload = loadScript;
</script>

<div id="map" style="width: 900px; height: 700px;"></div>

我正在寻找一种避免使用center: new google.maps.LatLng(41.923, 12.513)“手动”找到地图中心的方法。有没有办法让地图自动以三个坐标为中心?

【问题讨论】:

标签: javascript google-maps google-maps-api-3 google-maps-markers


【解决方案1】:

有一种更简单的方法,即扩展一个空的LatLngBounds,而不是从两点显式创建一个。 (详情请见this question

应该看起来像这样,添加到您的代码中:

//create empty LatLngBounds object
var bounds = new google.maps.LatLngBounds();
var infowindow = new google.maps.InfoWindow();    

for (i = 0; i < locations.length; i++) {  
  var marker = new google.maps.Marker({
    position: new google.maps.LatLng(locations[i][1], locations[i][2]),
    map: map
  });

  //extend the bounds to include each marker's position
  bounds.extend(marker.position);

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

//now fit the map to the newly inclusive bounds
map.fitBounds(bounds);

//(optional) restore the zoom level after the map is done scaling
var listener = google.maps.event.addListener(map, "idle", function () {
    map.setZoom(3);
    google.maps.event.removeListener(listener);
});

这样,你可以使用任意数量的点,并且不需要事先知道顺序。

在这里演示 jsFiddle:http://jsfiddle.net/x5R63/

【讨论】:

  • 谢谢,它有效!唯一阻止我接受答案的是缩放级别不再受到尊重。你知道如何让它再次工作吗? :)
  • @MultiformeIngegno 如果在fitBounds 之后使用setZoom 应该可以正常工作
  • @MultiformeIngegno 在fitBounds 对我进行简短测试后立即调用它;如果您仍有问题,请告诉我。
  • @metadept 如何在该中心位置设置标记?是否有可能获得界限?
  • map.panToBounds(bounds); 用于自动缩放。
【解决方案2】:

我认为你必须计算纬度最小值和经度最小值: 这是一个示例,其中包含用于将您的观点居中的功能:

//Example values of min & max latlng values
var lat_min = 1.3049337;
var lat_max = 1.3053515;
var lng_min = 103.2103116;
var lng_max = 103.8400188;

map.setCenter(new google.maps.LatLng(
  ((lat_max + lat_min) / 2.0),
  ((lng_max + lng_min) / 2.0)
));
map.fitBounds(new google.maps.LatLngBounds(
  //bottom left
  new google.maps.LatLng(lat_min, lng_min),
  //top right
  new google.maps.LatLng(lat_max, lng_max)
));

【讨论】:

    【解决方案3】:

    我已经尝试了这个主题的所有答案,但是下面的这个在我的项目上运行良好。

    Angular 7 和 AGM Core 1.0.0-beta.7

    <agm-map [latitude]="lat" [longitude]="long" [zoom]="zoom" [fitBounds]="true">
      <agm-marker latitude="{{localizacao.latitude}}" longitude="{{localizacao.longitude}}" [agmFitBounds]="true"
        *ngFor="let localizacao of localizacoesTec">
      </agm-marker>
    </agm-map>
    

    agm-marker 处的 [agmFitBounds]="true"agm-map 处的 [fitBounds]="true" 属性完成了这项工作

    【讨论】:

      【解决方案4】:

      另一个实现,基于之前的答案,但更精简:

      export class MapComponent {
          @ViewChild(GoogleMap) map: GoogleMap;
      
          markerList = [
              {
                  lat: 41.926979,
                  lng: 12.517385
              },
              {
                  lat: 41.914873,
                  lng: 12.506486
              },
              {
                  lat: 41.918574, 
                  lng: 12.507201
              }
          ]
      
          centralize() {
              const bounds = new google.maps.LatLngBounds();
              this.markerList.forEach((marker) => {
                  bounds.extend(new google.maps.LatLng(marker.lat, marker.lng))
              })
              this.map.fitBounds(bounds)
          }
      }
      

      您不需要创建“google.maps.Marker”,只需从 LatLng 创建一个实例,然后直接作为参数传递给边界扩展函数。

      【讨论】:

        【解决方案5】:

        要找到地图的确切中心,您需要将纬度/经度坐标转换为像素坐标,然后找到像素中心并将其转换回纬度/经度坐标。

        您可能不会注意到或介意漂移,具体取决于您在赤道以北或以南多远。你可以通过在setInterval中执行map.setCenter(map.getBounds().getCenter())来查看漂移,当它接近赤道时漂移会慢慢消失。

        您可以使用以下方法在纬度/经度和像素坐标之间进行转换。像素坐标基于完全放大的整个世界的平面,但您可以找到该平面的中心并将其切换回纬度/经度。

           var HALF_WORLD_CIRCUMFERENCE = 268435456; // in pixels at zoom level 21
           var WORLD_RADIUS = HALF_WORLD_CIRCUMFERENCE / Math.PI;
        
           function _latToY ( lat ) {
              var sinLat = Math.sin( _toRadians( lat ) );
              return HALF_WORLD_CIRCUMFERENCE - WORLD_RADIUS * Math.log( ( 1 + sinLat ) / ( 1 - sinLat ) ) / 2;
           }
        
           function _lonToX ( lon ) {
              return HALF_WORLD_CIRCUMFERENCE + WORLD_RADIUS * _toRadians( lon );
           }
        
           function _xToLon ( x ) {
              return _toDegrees( ( x - HALF_WORLD_CIRCUMFERENCE ) / WORLD_RADIUS );
           }
        
           function _yToLat ( y ) {
              return _toDegrees( Math.PI / 2 - 2 * Math.atan( Math.exp( ( y - HALF_WORLD_CIRCUMFERENCE ) / WORLD_RADIUS ) ) );
           }
        
           function _toRadians ( degrees ) {
              return degrees * Math.PI / 180;
           }
        
           function _toDegrees ( radians ) {
              return radians * 180 / Math.PI;
           }
        

        【讨论】:

          【解决方案6】:

          这项工作在 Angular 9 中为我工作:

            import {GoogleMap, GoogleMapsModule} from "@angular/google-maps";
            @ViewChild('Map') Map: GoogleMap; /* Element Map */
          
            locations = [
             { lat: 7.423568, lng: 80.462287 },
             { lat: 7.532321, lng: 81.021187 },
             { lat: 6.117010, lng: 80.126269 }
            ];
          
            constructor() {
             var bounds = new google.maps.LatLngBounds();
              setTimeout(() => {
               for (let u in this.locations) {
                var marker = new google.maps.Marker({
                 position: new google.maps.LatLng(this.locations[u].lat, 
                 this.locations[u].lng),
                });
                bounds.extend(marker.getPosition());
               }
          
               this.Map.fitBounds(bounds)
              }, 200)
            }
          

          它会根据指示的位置自动将地图居中。

          结果:

          【讨论】:

            【解决方案7】:

            我使用上面的方法设置地图边界,然后,而不是重置缩放级别,我 只需计算平均 LAT 和平均 LON 并将中心点设置为该位置。 我将所有 lat 值加到 latTotal 中,将所有 lon 值加到 lontotal 中,然后除以标记数。然后我将地图中心点设置为这些平均值。

            latCenter = latTotal / markercount; lonCenter = lontotal / 标记计数;

            【讨论】:

              【解决方案8】:

              我遇到了无法更改旧代码的情况,因此添加了这个 javascript 函数来计算中心点和缩放级别:

              //input
              var tempdata = ["18.9400|72.8200-19.1717|72.9560-28.6139|77.2090"];
              
              function getCenterPosition(tempdata){
              	var tempLat = tempdata[0].split("-");
              	var latitudearray = [];
              	var longitudearray = [];
              	var i;
              	for(i=0; i<tempLat.length;i++){
              		var coordinates = tempLat[i].split("|");
              		latitudearray.push(coordinates[0]);
              		longitudearray.push(coordinates[1]);
              	}
              	latitudearray.sort(function (a, b) { return a-b; });
              	longitudearray.sort(function (a, b) { return a-b; });
              	var latdifferenece = latitudearray[latitudearray.length-1] - latitudearray[0];
              	var temp = (latdifferenece / 2).toFixed(4) ;
              	var latitudeMid = parseFloat(latitudearray[0]) + parseFloat(temp);
              	var longidifferenece = longitudearray[longitudearray.length-1] - longitudearray[0];
              	temp = (longidifferenece / 2).toFixed(4) ;
              	var longitudeMid = parseFloat(longitudearray[0]) + parseFloat(temp);
              	var maxdifference = (latdifferenece > longidifferenece)? latdifferenece : longidifferenece;
              	var zoomvalue;	
              	if(maxdifference >= 0 && maxdifference <= 0.0037)  //zoom 17
              		zoomvalue='17';
              	else if(maxdifference > 0.0037 && maxdifference <= 0.0070)  //zoom 16
              		zoomvalue='16';
              	else if(maxdifference > 0.0070 && maxdifference <= 0.0130)  //zoom 15
              		zoomvalue='15';
              	else if(maxdifference > 0.0130 && maxdifference <= 0.0290)  //zoom 14
              		zoomvalue='14';
              	else if(maxdifference > 0.0290 && maxdifference <= 0.0550)  //zoom 13
              		zoomvalue='13';
              	else if(maxdifference > 0.0550 && maxdifference <= 0.1200)  //zoom 12
              		zoomvalue='12';
              	else if(maxdifference > 0.1200 && maxdifference <= 0.4640)  //zoom 10
              		zoomvalue='10';
              	else if(maxdifference > 0.4640 && maxdifference <= 1.8580)  //zoom 8
              		zoomvalue='8';
              	else if(maxdifference > 1.8580 && maxdifference <= 3.5310)  //zoom 7
              		zoomvalue='7';
              	else if(maxdifference > 3.5310 && maxdifference <= 7.3367)  //zoom 6
              		zoomvalue='6';
              	else if(maxdifference > 7.3367 && maxdifference <= 14.222)  //zoom 5
              		zoomvalue='5';
              	else if(maxdifference > 14.222 && maxdifference <= 28.000)  //zoom 4
              		zoomvalue='4';
              	else if(maxdifference > 28.000 && maxdifference <= 58.000)  //zoom 3
              		zoomvalue='3';
              	else
              		zoomvalue='1';
              	return latitudeMid+'|'+longitudeMid+'|'+zoomvalue;
              }

              【讨论】:

                【解决方案9】:

                如果有人遇到此线程,这是我对此的看法:

                这有助于防止非数值数据破坏确定latlng 的最终变量。

                它的工作原理是获取所有坐标,将它们解析为数组的单独 latlng 元素,然后确定每个元素的平均值。该平均值应该是中心(并且在我的测试用例中证明是正确的。)

                var coords = "50.0160001,3.2840073|50.014458,3.2778274|50.0169713,3.2750587|50.0180745,3.276742|50.0204038,3.2733474|50.0217796,3.2781737|50.0293064,3.2712542|50.0319918,3.2580816|50.0243287,3.2582281|50.0281447,3.2451177|50.0307925,3.2443178|50.0278165,3.2343882|50.0326574,3.2289809|50.0288569,3.2237612|50.0260081,3.2230589|50.0269495,3.2210104|50.0212645,3.2133541|50.0165868,3.1977592|50.0150515,3.1977341|50.0147901,3.1965286|50.0171915,3.1961636|50.0130074,3.1845098|50.0113267,3.1729483|50.0177206,3.1705726|50.0210692,3.1670394|50.0182166,3.158297|50.0207314,3.150927|50.0179787,3.1485753|50.0184944,3.1470782|50.0273077,3.149845|50.024227,3.1340514|50.0244172,3.1236235|50.0270676,3.1244474|50.0260853,3.1184879|50.0344525,3.113806";
                
                var filteredtextCoordinatesArray = coords.split('|');    
                
                    centerLatArray = [];
                    centerLngArray = [];
                
                
                    for (i=0 ; i < filteredtextCoordinatesArray.length ; i++) {
                
                      var centerCoords = filteredtextCoordinatesArray[i]; 
                      var centerCoordsArray = centerCoords.split(',');
                
                      if (isNaN(Number(centerCoordsArray[0]))) {      
                      } else {
                        centerLatArray.push(Number(centerCoordsArray[0]));
                      }
                
                      if (isNaN(Number(centerCoordsArray[1]))) {
                      } else {
                        centerLngArray.push(Number(centerCoordsArray[1]));
                      }                    
                
                    }
                
                    var centerLatSum = centerLatArray.reduce(function(a, b) { return a + b; });
                    var centerLngSum = centerLngArray.reduce(function(a, b) { return a + b; });
                
                    var centerLat = centerLatSum / filteredtextCoordinatesArray.length ; 
                    var centerLng = centerLngSum / filteredtextCoordinatesArray.length ;                                    
                
                    console.log(centerLat);
                    console.log(centerLng);
                
                    var mapOpt = {      
                    zoom:8,
                    center: {lat: centerLat, lng: centerLng}      
                    };
                

                【讨论】:

                  猜你喜欢
                  • 2012-07-01
                  • 2012-01-29
                  • 2020-03-10
                  • 2012-06-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多