Google Maps API v3: fitBounds'tan sonraZoom'u ayarlayabilir miyim?


201

Katıştırılmış bir Google Haritası'nda (API v3) çizmek istediğim bir dizi noktam var. Zoom seviyesi çok düşük (yani, çok uzaklaştırılmış) sürece sınırları tüm noktaları karşılamak istiyorum. Benim yaklaşımım şöyle oldu:

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

gmap.fitBounds(bounds); 
gmap.setZoom( Math.max(6, gmap.getZoom()) );

Bu işe yaramıyor. Son satır olan "gmap.setZoom ()", fitBounds'tan hemen sonra çağrılırsa haritanın zum düzeyini değiştirmez.

Bir sınırın yakınlaştırma seviyesini haritaya uygulamadan almanın bir yolu var mı? Bunu çözmek için başka fikirler?


1
Bkz. Stackoverflow.com/questions/4523023/using-setzoom-after-using-fitbounds-with-google-maps-api-v3
Mawg, Monica'yı

Yanıtlar:


337

Düzenleme : Aşağıdaki Matt Diamond'ın yorumuna bakın.

Anladım! Bunu dene:

map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, "idle", function() { 
  if (map.getZoom() > 16) map.setZoom(16); 
  google.maps.event.removeListener(listener); 
});

İhtiyaçlarınızı değiştirin.


76
Harika bir çözüm, beni çok fazla sorundan kurtardı. Sadece addListenerOnce yöntemini kullanarak daha da basitleştirebileceğinizi eklemek istedim ... bu şekilde, dinleyici kaydetmek ve manuel olarak kaldırmak zorunda değilsiniz, çünkü yöntem bununla ilgilenecektir.
Matt Diamond

9
Bu haritayı "atlama" olarak görme davranışına sahiptir. Bunun yerine "zoom_change" olayını dinleyin ve fitBounds () öğesini çağırmadan önce ayarlayın. Aşağıdaki cevabımı gör
Benjamin Sussman

Teşekkürler! google.maps.event.addListenerOnce (harita, "boşta", işlev () {} -> SugarCRM için harita paketim için harika çalıştı.
jjwdesign

Dinleyici benim için tetiklenmiyor. Bunu document.ready ve window.load dosyalarında denedim. Herhangi bir fikir? map nesnesi tamam ve addListener da denendi: `var map = $ (" # js-main-map-canvas "); var listener = google.maps.event.addListenerOnce (harita, "boşta", işlev () {alert ('merhaba');}); ``
Henrik Erlandsson

Henrik, $ ("# js-main-map-canvas") [0] veya $ ("# js-main-map-canvas") 'yi deneyin. Get (0);
Rafael

68

Uygulamalarımdan birinde benzer bir sorunu çözdüm. Sorunun açıklamasından biraz kafam karışmıştı, ama sanırım aynı hedefe sahipsin ...

Uygulamamda bir veya daha fazla işaretçi çizmek ve haritanın hepsini göstermesini sağlamak istedim. Sorun sadece fitBounds yöntemine güveniyordum, o zaman tek bir nokta olduğunda yakınlaştırma düzeyi maksimize olurdu - bu iyi değildi.

Çözüm, birçok nokta varken fitBounds ve yalnızca bir nokta varken setCenter + setZoom kullanmaktı.

if (pointCount > 1) {
  map.fitBounds(mapBounds);
}
else if (pointCount == 1) {
  map.setCenter(mapBounds.getCenter());
  map.setZoom(14);
}

5
Cevabınız Google Maps V3 ile ilgili sorunumu çözdü. Teşekkürler!
FR6

1
Aynı problemi yaşadım ve çözümünüz işe yaradı! Teşekkürler!
manubkk

Aynı yaklaşımı kendim deniyordum ama işe yaramadı çünkü zoom'u ayarlamadan önce setCenter () 'ı çağırmıyordum ... Hala bu adımın neden gerekli olduğunu merak ediyorum, ama yine de çalışıyor ... teşekkürler bir çok Jim!
daveoncode

Harita Merkezi yaşadığım sorunu çözdü! Güzel bir +1
Piotr Kula

1
İyi cevabınız için teşekkürler +1
Bharat Chodvadiya

44

Cevabı almak için bu sayfaya birçok kez geldim ve mevcut tüm cevaplar süper yardımcı olsa da, sorunumu tam olarak çözmediler.

google.maps.event.addListenerOnce(googleMap, 'zoom_changed', function() {
    var oldZoom = googleMap.getZoom();
    googleMap.setZoom(oldZoom - 1); //Or whatever
});

Temel olarak 'zoom_changed' olayının haritanın kullanıcı arayüzünün 'boşta' olayı beklediğimde meydana gelen “atlanmasını” engellediğini gördüm.

Umarım bu birine yardımcı olur!


4
Mükemmel, 'atlama / otomatik yakınlaştırma' davranışı da vardı. Tıpkı diğer okuyucular için bir not olarak: Benjamin'in yukarıda "addListener" yerine yaptığı gibi "addListenerOnce" kullandığınızdan emin olun veya tarayıcınızın neden sürekli çöktüğüne dikkat edin ;-)
Geert-Jan

6
Ayrıca, fitBounds()eğer zoom_changed
kullanacaksanız

1
Bunun için teşekkürler, v4 bir fitBounds (sınırları, minZoomLevel) olması gerektiği gibi görünüyor :)
Richard

3
Benjamin, bence kullanmak daha iyi bounds_changed, çünkü zum seviyesini koruduğunda zoom_changedtetiklenmesi gerekmiyor fitBounds. Girişim jsfiddle.net/rHeMp/10 bunu doğrulamıyor, ancak tanımlanmamış davranışa güvenmemelisiniz.
TMS

10

Ben sadece maxZoom önceden ayarlayıp, daha sonra kaldırarak bunu düzelttim. Örneğin:

map.setOptions({ maxZoom: 15 });
map.fitBounds(bounds);
map.setOptions({ maxZoom: null });

Çok fazla yakınlaştırmayı önlemek için açık ara en iyi çözüm. Basit ve sezgisel. Harita çizimi ve yeniden çizimi yok.
user2605793

Bu gerçekten de şimdiye kadarki en iyi yürüyüş yolu.
Downhillski

2
Bu, fitBounds çağırdıktan hemen sonra maxZoom sıfırlarsanız işe yaramaz, çünkü zoom asenkron olarak gerçekleşir (böylece maxZoom yakınlaştırdığı zaman null değerine geri döner). Sanırım sıfırlamak için "boşta" kadar beklemek bu düzeltmek olacaktır.
user987356

4

Yanılmıyorsam, tüm noktalarınızın haritada mümkün olan en yüksek yakınlaştırma seviyesine sahip olmasını istediğinizi varsayıyorum. Bunu haritanın zum düzeyini 16'ya başlatarak başardım (V3'te mümkün olan en yüksek zum seviyesi olup olmadığından emin değilim).

var map = new google.maps.Map(document.getElementById('map_canvas'), {
  zoom: 16,
  center: marker_point,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

Sonra bundan sonra bir şeyler yaptım:

var bounds = new google.maps.LatLngBounds();

// You can have a loop here of all you marker points
// Begin loop
bounds.extend(marker_point);
// End loop

map.fitBounds(bounds);

Sonuç: Başarı!


3

Kullanırım:

gmap.setZoom(24); //this looks a high enough zoom value
gmap.fitBounds(bounds); //now the fitBounds should make the zoom value only less

Bu, kodunuza göre 24'ten küçük olanı ve gerekli yakınlaştırma düzeyini kullanacaktır, ancak muhtemelen yakınlaştırmayı yine de değiştirir ve ne kadar uzaklaştırdığınızı umursamaz.


Bunu söylemekten nefret ediyorum, ama bu cevap gibi göründüğü kadar garip, şimdiye kadar işe yarayan tek şey ve 3 gün boyunca 4-5 saat arıyordum. Yine de daha iyi bir çözüm arıyor olacak.
Allov

3

Lütfen şunu deneyin:

map.fitBounds(bounds);

// CHANGE ZOOM LEVEL AFTER FITBOUNDS
zoomChangeBoundsListener = google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
  if (this.getZoom()){
    this.setZoom(15);
  }
});
setTimeout(function(){
  google.maps.event.removeListener(zoomChangeBoundsListener)
}, 2000);

2

Aynı sorunu vardı ve aşağıdaki kodu kullanarak çözmeyi başardı. Bu listener ( google.maps.addListenerOnce()) olayı map.fitBounds(), yürütüldükten hemen sonra yalnızca bir kez tetiklenir . Yani, gerek yok

  1. Dinleyiciyi takip edin ve manuel olarak kaldırın veya
  2. Harita olana kadar bekleyin idle.

Başlangıçta uygun zoom seviyesini ayarlar ve olay dinleyicinin süresi dolduğundan kullanıcının başlangıç ​​zoom seviyesinin ötesine yakınlaştırıp uzaklaşmasına olanak tanır. Örneğin, yalnızca google.maps.addListener()çağrıldıysa, kullanıcı hiçbir zaman belirtilen yakınlaştırma seviyesini geçemez (durumda 4). Uyguladığımızdan beri google.maps.addListenerOnce(), kullanıcı istediği seviyeye yakınlaşabilecektir.

map.fitBounds(bounds);

var zoom_level_for_one_marker = 4;

google.maps.event.addListenerOnce(map, 'bounds_changed', function(event){
   if (this.getZoom() >= zoom_level_for_one_marker){  
       this.setZoom(zoom_level_for_one_marker) 
   }
});

2

Aynı sorunu vardı, harita üzerinde birçok işaret sığdırmak için gerekli. Bu davamı çözdü:

  1. Sınırları beyan et
  2. Koderoid tarafından sağlanan şemayı kullanın (her marker seti için bounds.extend(objLatLng))
  3. Harita tamamlandıktan SONRA fitboundları yürütün:

    google.maps.event.addListenerOnce(map, 'idle', function() { 
        map.fitBounds( bounds );
    });

2

Aramadan önce kontrolü yapan bir çözüm buldum, fitBoundsböylece yakınlaştırmıyorsunuz ve aniden uzaklaştırmıyorsunuz

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

var minLatSpan = 0.001;
if (bounds.toSpan().lat() > minLatSpan) {
    gmap.fitBounds(bounds); 
} else {
    gmap.setCenter(bounds.getCenter());
    gmap.setZoom(16);
}

İstediğiniz yere ulaşmak için minLatSpan değişkeni ile biraz oynamak zorunda kalacaksınız. Hem yakınlaştırma düzeyine hem de harita tuvalinin boyutlarına göre değişir.

Enlem yerine boylam da kullanabilirsiniz


Benim için çalışıyor, ama minLatSpan kullanmıyorum - Yakınlaştırma ayarını yalnızca 1 işaretçi haritadayken ayarlamam gerekir. Bu yüzden sadece 1'den fazla işaretleyici olup olmadığını kontrol ediyorum.
Micer

2

Birçok yanlış veya çok karmaşık çözüm gördüm, bu yüzden çalışan, zarif bir çözüm yayınlamaya karar verdim .

Nedeni setZoom()beklediğiniz gibi çalışmaz, bu fitBounds()eşzamansızdır, bu nedenle yakınlaştırmayı hemen güncelleyeceğine dair hiçbir garanti vermez, ancak buna yapılan çağrıya setZoom()dayanır.

Göz önünde bulundurabileceğiniz şey, minZoomarama yapmadan önce harita seçeneğini ayarlamak ve fitBounds()tamamlandıktan sonra temizlemek (böylece kullanıcılar istedikleri takdirde manuel olarak uzaklaştırabilirler):

var bounds = new google.maps.LatLngBounds();
// ... (extend bounds with all points you want to fit)

// Ensure the map does not get too zoomed out when fitting the bounds.
gmap.setOptions({minZoom: 6});
// Clear the minZoom only after the map fits the bounds (note that
// fitBounds() is asynchronous). The 'idle' event fires when the map
// becomes idle after panning or zooming.
google.maps.event.addListenerOnce(gmap, 'idle', function() {
  gmap.setOptions({minZoom: null});
});

gmap.fitBounds(bounds);

Ayrıca, maksimum zumu da sınırlamak istiyorsanız, maxZoommülkle aynı numarayı uygulayabilirsiniz .

MapOptions belgelerine bakın .


1

Bunu, uydu görüntülerinin mevcut olacağını bildiğim için yakınlaştırma düzeyinin ayarlanan bir düzeyi aşmamasını sağlamak için kullanıyorum.

zoom_changedEtkinliğe bir dinleyici ekleyin . Bu, kullanıcı arayüzündeki yakınlaştırma kontrolünü de kontrol etmenin ek avantajına sahiptir.

Yalnızca setZoomgerektiğinde çalıştır , bu nedenle bir ififade Math.maxveyaMath.min

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() > 19 ) { 
        map.setZoom(19); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

Uzaklaştırmayı çok fazla önlemek için:

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() < 6 ) { 
        map.setZoom(6); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

1

Bu işlevde, yalnızca işlev herhangi bir geometriyi kabul ettiği için geometri türünü saklamak için dinamik olarak meta veriler eklemeniz gerekir.

"fitGeometries" bir harita nesnesini genişleten bir JSON işlevidir.

"geometriler" bir MVCArray () değil, genel bir javascript dizisidir.

geometry.metadata = { type: "point" };
var geometries = [geometry];

fitGeometries: function (geometries) {
    // go and determine the latLngBounds...
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0; i < geometries.length; i++) {
        var geometry = geometries[i];
        switch (geometry.metadata.type)
        {
            case "point":
                var point = geometry.getPosition();
                bounds.extend(point);
                break;
            case "polyline":
            case "polygon": // Will only get first path
                var path = geometry.getPath();
                for (var j = 0; j < path.getLength(); j++) {
                    var point = path.getAt(j);
                    bounds.extend(point);
                }
                break;
        }
    }
    this.getMap().fitBounds(bounds);
},

Alternatif olarak, tüm çalışmaları LatLngBounds nesnesinde bir extend () yöntemi olduğunu bilmeden yaptım. Bu çok daha kolay olurdu.
CrazyEnigma

1

bu çalışma benim için API v3 ile ancak sabit zum ayarıyla:

var bounds = new google.maps.LatLngBounds();
// extend bounds with each point

gmap.setCenter(bounds.getCenter()); 
gmap.setZoom( 6 );

1

Benim gibi, eğer dinleyicilerle oynamak istemiyorsanız, bu ile geldiğim basit bir çözümdür: Haritaya kesinlikle böyle gereksinimlerinize göre çalışan bir yöntem ekleyin:

    map.fitLmtdBounds = function(bounds, min, max){
        if(bounds.isEmpty()) return;
        if(typeof min == "undefined") min = 5;
        if(typeof max == "undefined") max = 15;

        var tMin = this.minZoom, tMax = this.maxZoom;
        this.setOptions({minZoom:min, maxZoom:max});
        this.fitBounds(bounds);
        this.setOptions({minZoom:tMin, maxZoom:tMax});
    }

o zaman çağırabilir map.fitLmtdBounds(bounds)yerine map.fitBounds(bounds)tanımlanan zoom aralığında altında sınırlarını belirlemek için ... ya map.fitLmtdBounds(bounds,3,5)zoom aralığı geçersiz kılmak için ..


0

Lütfen bunu deneyin.

// Find out what the map's zoom level is
zoom = map.getZoom();
if (zoom == 1) {
  // If the zoom level is that low, means it's looking around the
world.
  // Swap the sw and ne coords
  viewportBounds = new
google.maps.LatLngBounds(results[0].geometry.location, initialLatLng);
  map.fitBounds(viewportBounds);
}

Bu size yardımcı olacaksa.

Herşey gönlünce olsun


0

Sınırların hesaplanmasından sonra, sol üst ve sağ alt köşe arasındaki mesafeyi kontrol edebilirsiniz; o zaman mesafeyi test ederek zum düzeyini anlayabilirsiniz (eğer mesafe çok uzaksa zum seviyesi düşük olurdu) o zaman setbound yöntemini veya setZoom'u kullanarak daha fazlasını seçebilirsiniz.


0

Bunu önermek istemiyorum, ama denemeniz gerekiyorsa - ilk çağrı

gmap.fitBounds(bounds);

Sonra yeni bir Thread / AsyncTask oluşturun, 20-50ms kadar uyutun ve sonra arayın

gmap.setZoom( Math.max(6, gmap.getZoom()) );

UI iş parçacığından ( onPostExecuteAsyncTask için bir işleyici veya yöntem kullanın).

Çalışıp çalışmadığını bilmiyorum, sadece bir öneri. Bunun dışında zum seviyesini bir şekilde noktalarınızdan kendiniz hesaplamanız, çok düşük olup olmadığını kontrol etmeniz, düzeltmeniz ve ardındangmap.setZoom(correctedZoom)


0

'Bounds_changed' doğru şekilde tetiklenmiyorsa (bazen Google koordinatları mükemmel bir şekilde kabul etmiyor gibi görünüyorsa), bunun yerine 'center_changed' kullanmayı düşünün.

'Center_changed' olayı fitBounds () her çağrıldığında tetiklenir, ancak harita taşındıktan hemen sonra ve zorunlu olarak gerçekleşmez.

Normal durumlarda, 'boşta' hala en iyi olay dinleyicisidir, ancak bu birkaç kişinin fitBounds () çağrılarıyla garip sorunlarla karşılaşmasına yardımcı olabilir.

Google Maps fitBounds geri aramasına bakın


0

Başka bir çözümle karşılaşmak için - "bounds_changed olayını dinle ve sonra yeni zum ayarla" yaklaşımının benim için güvenilir bir şekilde çalışmadığını gördüm. Bazen fitBoundsharita tamamen başlatılmadan önce aradığımı düşünüyorum ve başlatma, fitBoundssınırları ve yakınlaştırma seviyesini değiştirmeden önce dinleyiciyi kullanacak bir bounds_changed olayına neden oluyordu . Şimdiye kadar çalışıyor gibi görünüyor bu kod ile sona erdi:

// If there's only one marker, or if the markers are all super close together,
// `fitBounds` can zoom in too far. We want to limit the maximum zoom it can
// use.
//
// `fitBounds` is asynchronous, so we need to wait until the bounds have
// changed before we know what the new zoom is, using an event handler.
//
// Sometimes this handler gets triggered by a different event, before
// `fitBounds` takes effect; that particularly seems to happen if the map
// hasn't been fully initialized yet. So we don't immediately remove the
// listener; instead, we wait until the 'idle' event, and remove it then.
//
// But 'idle' might happen before 'bounds_changed', so we can't set up the
// removal handler immediately. Set it up in the first event handler.

var removeListener = null;
var listener = google.maps.event.addListener(map, 'bounds_changed', () => {
  console.log(map.getZoom());
  if (map.getZoom() > 15) {
    map.setZoom(15);
  }

  if (!removeListener) {
    removeListener = google.maps.event.addListenerOnce(map, 'idle', () => {
      console.log('remove');
      google.maps.event.removeListener(listener);
    });
  }
});

0

Benim için en kolay çözüm şuydu:

map.fitBounds(bounds);

function set_zoom() {
    if(map.getZoom()) {map.setZoom(map.getZoom() - 1);}
    else {setTimeout(set_zoom, 5);}
}
setTimeout(set_zoom, 5);

-1
google.maps.event.addListener(marker, 'dblclick', function () {
    var oldZoom = map.getZoom(); 
    map.setCenter(this.getPosition());
    map.setZoom(parseInt(oldZoom) + 1);
});

-3

Tek yaptığım:

map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));

Ve V3 API üzerinde çalışıyor.


map.setCenter yalnızca bir özelliği, latlng'yi kabul eder ve haritanın getBoundsZoomLevel gibi bir işlevi yoktur
Viktor

Bu yazıyı gördükten sonra getBoundsZoomLevel gibi bir işlev olduğunu düşündüm ve olmadığını fark ettikten sonra hayal kırıklığına uğradım.
sedran

getBoundsZoomLevel () Google Maps V2 API'sinde mevcut olduğunu ve V3 API'sında mevcut olmadığını düşünüyorum
Kush
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.