2010-10-10 6 views
11

Google Maps API V3 'u kullanarak haritayı sürükleyebileceğiniz sınırlar belirlemeye çalışıyorum İşte oldukça iyi çalışan V2 http://econym.org.uk/gmap/example_range.htm için çözüm.Google Maps API V3: harita sınırlarını sınırla

Ancak, API V3 ile o kadar da iyi değil: aynı checkbounds() işlevini kullandığınızda, map.setCenter() haritanın merkezini değiştirirken, haritaya ulaştığınızda harita seğiriyor.

Nasıl düzeltilir? API V3 için çözüm nedir?

cevap

19

Aynı problemi yaşadım, ama bunu çözmeliyim (aynı işlev, dinlemenin olayı "move" veya "drag" den "center_changed" e değiştirildi, çekicilik gibi çalışıyor !:

google.maps.event.addListener(map,'center_changed',function() { checkBounds(); }); 

function checkBounds() {  
    if(! allowedBounds.contains(map.getCenter())) { 
     var C = map.getCenter(); 
     var X = C.lng(); 
     var Y = C.lat(); 

     var AmaxX = allowedBounds.getNorthEast().lng(); 
     var AmaxY = allowedBounds.getNorthEast().lat(); 
     var AminX = allowedBounds.getSouthWest().lng(); 
     var AminY = allowedBounds.getSouthWest().lat(); 

     if (X < AminX) {X = AminX;} 
     if (X > AmaxX) {X = AmaxX;} 
     if (Y < AminY) {Y = AminY;} 
     if (Y > AmaxY) {Y = AmaxY;} 

     map.setCenter(new google.maps.LatLng(Y,X)); 
    } 
} 
+0

Bunu kullandım ve harika çalışıyor. Şerefe! –

+5

'allowedBounds' nedir? – travis

+1

allowedBounds bir [LatLngBounds nesne] olduğu (https://developers.google.com/maps/documentation/javascript/reference#LatLngBounds) (enlem/boylam temelde bir çift). Bu gerçekten iyi çalışıyor BTW, benim için tam olarak ne gerekiyorsa yapar! – strikernl

4

Bu komut ilk sınırları (allowedBounds) alır ve drag ve zoom_changed üzerinde sınırları sınırlar. Ayrıca yakınlaştırma < 7.

var allowedBounds = false; 

google.maps.event.addListener(map, 'idle', function() { 
if (!allowedBounds) { 
    allowedBounds = map.getBounds(); 
} 
}); 

google.maps.event.addListener(map, 'drag', checkBounds); 
google.maps.event.addListener(map, 'zoom_changed', checkBounds); 

function checkBounds() { 

if (map.getZoom() < 7) map.setZoom(7); 

if (allowedBounds) { 

    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 currentBounds = map.getBounds(); 
    var current_ne_lng = currentBounds.getNorthEast().lng(); 
    var current_ne_lat = currentBounds.getNorthEast().lat(); 
    var current_sw_lng = currentBounds.getSouthWest().lng(); 
    var current_sw_lat = currentBounds.getSouthWest().lat(); 

    var currentCenter = map.getCenter(); 
    var centerX = currentCenter.lng(); 
    var centerY = currentCenter.lat(); 

    if (current_ne_lng > allowed_ne_lng) centerX = centerX-(current_ne_lng-allowed_ne_lng); 
    if (current_ne_lat > allowed_ne_lat) centerY = centerY-(current_ne_lat-allowed_ne_lat); 
    if (current_sw_lng < allowed_sw_lng) centerX = centerX+(allowed_sw_lng-current_sw_lng); 
    if (current_sw_lat < allowed_sw_lat) centerY = centerY+(allowed_sw_lat-current_sw_lat); 

    map.setCenter(new google.maps.LatLng(centerY,centerX)); 
} 
} 
+0

Bu, yalnızca merkezi değil, dış sınırları dikkate alan bulduğum tek cevabı. Sadece merkeze güvenmek, yakınlaştırma seviyesine bağlı olarak, istenilen alanın dışında hala iyi bir şekilde hareket etmenizi sağlar. – James

1

Teşekkür @sairafi üzerinde sınırlıdır. Cevabınız çok got me yakındım getti getBounds undefined olduğu yerde bir hata oluştu, bu yüzden haritanın ilk önce tamamen yüklendiğinden emin olmak için başka bir dinleyiciye sardım.

google.maps.event.addListenerOnce(map, 'tilesloaded', function() { 
    allowedBounds = map.getBounds(); 
    google.maps.event.addListener(map,'center_changed',function() { checkBounds(allowedBounds); }); 
}); 

// Limit map area 
function checkBounds(allowedBounds) { 

if(!allowedBounds.contains(map.getCenter())) { 
    var C = map.getCenter(); 
    var X = C.lng(); 
    var Y = C.lat(); 

    var AmaxX = allowedBounds.getNorthEast().lng(); 
    var AmaxY = allowedBounds.getNorthEast().lat(); 
    var AminX = allowedBounds.getSouthWest().lng(); 
    var AminY = allowedBounds.getSouthWest().lat(); 

    if (X < AminX) {X = AminX;} 
    if (X > AmaxX) {X = AmaxX;} 
    if (Y < AminY) {Y = AminY;} 
    if (Y > AmaxY) {Y = AmaxY;} 

    map.setCenter(new google.maps.LatLng(Y,X)); 
} 
} 
0
southWest = new google.maps.LatLng(48.59475380744011,22.247364044189453); 
      northEast = new google.maps.LatLng(48.655344320891444,22.352420806884766); 
      var limBound = new google.maps.LatLngBounds(southWest,northEast); 
      var lastCenter; 

      var option = {zoom:15, 
      center: limBound.getCenter(), 
      mapTypeId: google.maps.MapTypeId.ROADMAP}; 
      var map = new google.maps.Map(document.getElementById('divMap'),option); 
      google.maps.event.addListener(map,'zoom_changed', function() { 
       minZoom(15); 
       }); 
      google.maps.event.addListener(map,'drag',function(e){ 
       limitBound(limBound); 
       }); 

     function minZoom(minZoom){ 
       if (map.getZoom()<minZoom) 
       {map.setZoom(minZoom);} 
      };  

     function limitBound(bound) 
     { 
      if (bound.getNorthEast().lat() > map.getBounds().getNorthEast().lat() 
       && bound.getNorthEast().lng() > map.getBounds().getNorthEast().lng() 
       && bound.getSouthWest().lat() < map.getBounds().getSouthWest().lat() 
       && bound.getSouthWest().lng() < map.getBounds().getSouthWest().lng()) 
       { 
        lastCenter=map.getCenter(); 
        $('#divText').text(lastCenter.toString()); 
        } 
       if (bound.contains(map.getCenter())) 
       { 
        map.setCenter(lastCenter); 
        } 
      } 
0

@sairafi ve her iki cevaplar için

sayesinde @devin. 'u bulamıyorum, çünkü Chrome'u/Windows 7'de çalışıyorum, çünkü .comtains() işareti, sınırı vurduğunuz anda hem doğru hem de yanlış olarak uyarılır.

Yani panto()

için alt kısımdaki setCenter() değişti ikinci sorun ilk yüklemede sınırları belirleme, sen (google.maps.event.addListenerOnce kullanmak harita var olmasıydı, 'boşta' ...) olayı aksi takdirde o anda görüntülenebilir haritanın sınırlarını sıfırlamaya devam eder.

Son olarak, izleme merkezleri için sürükleme etkinliğini, daha sorunsuz çalışmanın bir nedeni olarak kullanıyorum.

çıkan kod şudur:

google.maps.event.addListenerOnce(map,'idle',function() { 
     allowedBounds = map.getBounds(); 
    }); 
    google.maps.event.addListener(map,'drag',function() { 
     checkBounds(); 
    }); 
    function checkBounds() {  
     if(! allowedBounds.contains(map.getCenter())) 
     { 
      var C = map.getCenter(); 
      var X = C.lng(); 
      var Y = C.lat(); 
      var AmaxX = allowedBounds.getNorthEast().lng(); 
      var AmaxY = allowedBounds.getNorthEast().lat(); 
      var AminX = allowedBounds.getSouthWest().lng(); 
      var AminY = allowedBounds.getSouthWest().lat(); 
      if (X < AminX) {X = AminX;} 
      if (X > AmaxX) {X = AmaxX;} 
      if (Y < AminY) {Y = AminY;} 
      if (Y > AmaxY) {Y = AmaxY;} 
      map.panTo(new google.maps.LatLng(Y,X)); 
     } 
    } 
6

Ayrıca koordinatları, eğri bozulmasını sarma dikkate almak gerekir ve harita boyutlandırır veya In/out yakınlaştırır eğer bağlı boyutlara centerizing olabilir. Bu özellikle, haritanız haritanın büyük bir yüzdesini (örneğin bir kıta gibi) alıyorsa gereklidir.

CheckBounds() ile ilgili sorunlardan biri, enlem değerlerinin sınırlarını sınırlayan doğrusal olmayan distorsiyonu olan kuzey/güney kutuplarına yakın olan enlem değerlerini hesaba katmamasıdır (I). Her durumda çalışmayan yaklaşık sihirli sayı çarpanları kullanın). Doğru olarak, dünya koordinatlarındaki gerçek hedef merkez noktasını hedef gerçek enlem konumuna getirmekten ziyade, sınırların dünya koordinatları açısından ne kadar uzak olduğunu görmek için sınırları 2d dünya koordinatlarına dönüştürmelisiniz.Boylam değerleri için, bu bir çok sorun gibi görünmüyor ve doğrusal kırpma yaklaşımı yeterince doğru görünüyor, asıl konu aşağıdaki kodda (bir şekilde) hesaplanan boylam koordinatlarının sarılmasıdır. checkBounds() için

// 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., uygun 2d Dünya 2 enlem/Ing değerleri verilen haritanın merkezine koordinat almak için, map.getProjection(). fromLatLngToPoint() kullanın. 2 noktayı karşılaştırın, aralarındaki doğrusal farkı bulun ve map.getProjection(). FromPointToLatLng() öğesini kullanarak dünya koordinatlarındaki farkı lat/lng ile eşleştirin. Bu, lat/lng birimlerinde doğru klip ofsetleri verecektir.