在谷歌地图API v3中自动居中多个标记的地图

这是我用来显示一个有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)。是否有一种方法可以自动将地图置于三个坐标的中心?

242765 次浏览

我认为你必须计算纬度min和经度min: 下面是一个示例,函数用于中心化你的观点:

//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)
));

有一个更简单的方法,扩展一个空LatLngBounds,而不是从两个点显式地创建一个。(详见这个问题)

应该是这样的,添加到你的代码:

//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/

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

你可能不会注意到或介意这种漂移,这取决于你在赤道以北或以南多远。你可以通过在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;
}
我使用上面的方法来设置地图边界,然后,而不是重置缩放级别,我 只需计算平均LAT和平均LON,并将中心点设置为该位置。 我把所有的lat值加到latTotal中,把所有的lon值加到lontotal中,然后除以标记的数量。然后我将地图中心点设置为这些平均值

latCenter = latTotal / markcount;

. lonCenter = lontotal / markercount

我有一个情况,我不能改变旧的代码,所以添加了这个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;
}

以下是我的看法,以防有人看到这个帖子:

这有助于防止非数值数据破坏决定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}
};

这个工作为我在角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)
}

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

结果:

enter image description here

我已经尝试了这个主题的所有答案,但下面这个在我的项目中工作得很好。

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>

属性[agmFitBounds]="true"agm-marker[fitBounds]="true"agm-map可以完成这项工作

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

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中创建一个实例,并直接将其作为参数传递给边界扩展函数。