Si potrebbe anche prendere in considerazione incarto coordinate, distorsione curva e centerizing alle dimensioni rilegati se la mappa ridimensiona o zoom in/out. Questo è particolarmente necessario se i tuoi limiti occupano una grande percentuale dell'intera mappa (ad esempio, come un continente).
Uno dei problemi con checkBounds() è che non tiene conto dei valori di latitudine vicini ai poli nord/sud, che hanno una distorsione non lineare che limita i limiti in accuratezza (I utilizzare moltiplicatori di numeri magici approssimativi che non funzioneranno in tutte le situazioni). A destra, dovresti prima convertire i limiti in coordinate del mondo 2d lineari per vedere quanto è lontano dai confini in termini di coordinate del mondo, piuttosto che mappare il vero punto centrale del bersaglio in coordinate mondiali con la posizione attuale di latitudine bersaglio.Per i valori di longitudine, questo non sembra molto problema e l'approccio di clipping lineare sembra abbastanza accurato, il problema principale è con l'avvolgimento delle coordinate di longitudine che è rappresentato (in qualche modo) nel codice sottostante.
// 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 Per checkBounds(), per ottenere una corretta coordinare mondo 2d dal centro della mappa, data 2 valori LAT/LNG, utilizzare map.getProjection(). FromLatLngToPoint(). Confrontate i 2 punti, individuate la differenza lineare tra di loro e mappate la differenza delle coordinate del mondo a lat/lng usando map.getProjection(). FromPointToLatLng(). Ciò ti fornirà offset di clip accurati in unità lat/lng.
Ho usato questo e funziona fantastico. Saluti! –
a cosa è impostato 'allowedBounds'? – travis
allowedBounds è un [oggetto LatLngBounds] (https://developers.google.com/maps/documentation/javascript/reference#LatLngBounds) (in pratica una coppia di latitudini/longitudini). Questo funziona davvero bene BTW, fa esattamente quello che dovrebbe per me! – strikernl