También podría ser necesario considerar envolver coordenadas, la distorsión de la curva, y centerizing a las dimensiones de la envolvente si el mapa cambia el tamaño o el zoom in/out. Esto es especialmente necesario si sus límites ocupan un gran porcentaje del mapa completo (por ejemplo, como un continente).
Uno de los problemas con checkBounds(), sin embargo, es que no toma en cuenta que la latitud valores cercanos al norte/polos sur, que tienen la distorsión no lineal que hacen que la limitación de los límites de precisión-(I usa multiplicadores de números mágicos aproximados que no funcionarán en todas las situaciones). A la derecha, primero debes convertir los límites a las coordenadas del mundo 2d lineales para ver qué tan lejos están de los límites en términos de coordenadas mundiales, que mapear el punto central real del objetivo en coordenadas mundiales con la posición de latitud real del objetivo.Para los valores de longitud, esto no parece ser un problema y el enfoque de recorte lineal parece lo suficientemente preciso, el problema principal es el ajuste de las coordenadas de longitud que se contabiliza (algo) en el siguiente código.
// Persitant variables
var allowedBounds; // assign something here
var lastValidCenter; // initialize this using map.getCenter()
function checkBounds() { // when bounds changes due to resizing or zooming in/out
var currentBounds = map.getBounds();
if (currentBounds == null) return;
var allowed_ne_lng = allowedBounds.getNorthEast().lng();
var allowed_ne_lat = allowedBounds.getNorthEast().lat();
var allowed_sw_lng = allowedBounds.getSouthWest().lng();
var allowed_sw_lat = allowedBounds.getSouthWest().lat();
var wrap;
var cc = map.getCenter();
var centerH = false;
var centerV = false;
// Check horizontal wraps and offsets
if (currentBounds.toSpan().lng() > allowedBounds.toSpan().lng()) {
centerH = true;
}
else { // test positive and negative wrap respectively
wrap = currentBounds.getNorthEast().lng() < cc.lng();
var current_ne_lng = !wrap ? currentBounds.getNorthEast().lng() : allowed_ne_lng +(currentBounds.getNorthEast().lng() + 180) + (180 - allowed_ne_lng);
wrap = currentBounds.getSouthWest().lng() > cc.lng();
var current_sw_lng = !wrap ? currentBounds.getSouthWest().lng() : allowed_sw_lng - (180-currentBounds.getSouthWest().lng()) - (allowed_sw_lng+180);
}
// Check vertical wraps and offsets
if (currentBounds.toSpan().lat() > allowedBounds.toSpan().lat()) {
centerV = true;
}
else { // test positive and negative wrap respectively
wrap = currentBounds.getNorthEast().lat() < cc.lat(); if (wrap) { alert("WRAp detected top") } // else alert("no wrap:"+currentBounds); wrap = false;
var current_ne_lat = !wrap ? currentBounds.getNorthEast().lat() : allowed_ne_lat + (currentBounds.getNorthEast().lat() +90) + (90 - allowed_ne_lat);
wrap = currentBounds.getSouthWest().lat() > cc.lat(); if (wrap) { alert("WRAp detected btm") } //alert("no wrap:"+currentBounds);
var current_sw_lat = !wrap ? currentBounds.getSouthWest().lat() : allowed_sw_lat - (90-currentBounds.getSouthWest().lat()) - (allowed_sw_lat+90);
}
// Finalise positions
var centerX = cc.lng();
var centerY = cc.lat();
if (!centerH) {
if (current_ne_lng > allowed_ne_lng) centerX -= current_ne_lng-allowed_ne_lng;
if (current_sw_lng < allowed_sw_lng) centerX += allowed_sw_lng-current_sw_lng;
}
else {
centerX = allowedBounds.getCenter().lng();
}
if (!centerV) {
if (current_ne_lat > allowed_ne_lat) {
centerY -= (current_ne_lat-allowed_ne_lat) * 3; // approximation magic numbeer. Adjust as u see fit, or use a more accruate pixel measurement.
}
if (current_sw_lat < allowed_sw_lat) {
centerY += (allowed_sw_lat-current_sw_lat)*2.8; // approximation magic number
}
}
else {
centerY = allowedBounds.getCenter().lat();
}
map.setCenter(lastValidCenter = new google.maps.LatLng(centerY,centerX));
}
function limitBound(bound) // Occurs during dragging, pass allowedBounds to this function in most cases. Requires persistant 'lastValidCenter=map.getCenter()' var reference.
{
var mapBounds = map.getBounds();
if ( mapBounds.getNorthEast().lng() >= mapBounds.getSouthWest().lng() && mapBounds.getNorthEast().lat() >= mapBounds.getSouthWest().lat() // ensure no left/right, top/bottom wrapping
&& bound.getNorthEast().lat() > mapBounds.getNorthEast().lat() // top
&& bound.getNorthEast().lng() > mapBounds.getNorthEast().lng() // right
&& bound.getSouthWest().lat() < mapBounds.getSouthWest().lat() // bottom
&& bound.getSouthWest().lng() < mapBounds.getSouthWest().lng()) // left
{
lastValidCenter=map.getCenter(); // valid case, set up new valid center location
}
// if (bound.contains(map.getCenter()))
// {
map.panTo(lastValidCenter);
// }
}
// Google map listeners
google.maps.event.addListener(map, 'zoom_changed', function() {
//var zoom = map.getZoom();
checkBounds();
});
google.maps.event.addListener(map, "bounds_changed", function() {
checkBounds();
});
google.maps.event.addListener(map, 'center_changed', function() {
limitBound(allowedBounds);
});
p.s Para checkBounds(), para obtener la coordenada mundo 2d adecuada desde el centro del mapa, teniendo en cuenta los valores de 2 LAT/LNG, utilice map.getProjection(). FromLatLngToPoint(). Compara los 2 puntos, encuentra la diferencia lineal entre ellos y asigna la diferencia en las coordenadas del mundo a lat/lng usando map.getProjection(). FromPointToLatLng(). Esto le proporcionará correcciones de clip precisas en unidades lat/lng.
Lo usé y funciona increíble. ¡Aclamaciones! –
¿cómo se configura 'allowedBounds'? – travis
allowedBounds es un [objeto LatLngBounds] (https://developers.google.com/maps/documentation/javascript/reference#LatLngBounds) (básicamente un par de latitudes/longitudes). Esto funciona muy bien BTW, ¡hace exactamente lo que debería hacer por mí! – strikernl