Google Maps v3: Durchsetzung von min. Zoomstufe bei Verwendung von fitBounds

78

Ich zeichne eine Reihe von Markierungen auf einer Karte (mit v3 der Karten-API).

In v2 hatte ich den folgenden Code:

  bounds = new GLatLngBounds();

  ... loop thru and put markers on map ...
  bounds.extend(point);
  ... end looping

  map.setCenter(bounds.getCenter());
  var level = map.getBoundsZoomLevel(bounds);
  if ( level == 1 ) 
    level = 5;
  map.setZoom(level > 6 ? 6 : level);

Und das funktioniert gut, um sicherzustellen, dass auf der Karte immer ein angemessener Detaillierungsgrad angezeigt wird.

Ich versuche, diese Funktionalität in Version 3 zu duplizieren, aber setZoom und fitBounds scheinen nicht zusammenzuarbeiten:

... loop thru and put markers on the map
  var ll = new google.maps.LatLng(p.lat,p.lng);
  bounds.extend(ll);
... end loop

var zoom = map.getZoom();
map.setZoom(zoom > 6 ? 6 : zoom);
map.fitBounds(bounds);

Ich habe eine andere Permutation ausprobiert (z. B. Verschieben der fitBounds vor dem setZoom), aber nichts, was ich mit setZoom mache, scheint die Karte zu beeinflussen. Vermisse ich etwas Gibt es eine Möglichkeit, dies zu tun?

chris
quelle

Antworten:

135

Bei dieser Diskussion über Google Groups habe ich festgestellt, dass der Zoom beim Ausführen von fitBounds grundsätzlich asynchron erfolgt, sodass Sie das Ereignis zum Ändern von Zoom und Grenzen erfassen müssen. Der Code im letzten Beitrag hat bei mir mit einer kleinen Änderung funktioniert ... so wie es aussieht, können Sie nicht mehr als 15 vollständig zoomen. Verwenden Sie daher die Idee aus dem vierten Beitrag, um ein Flag zu setzen, das nur beim ersten Mal ausgeführt wird.

// Do other stuff to set up map
var map = new google.maps.Map(mapElement, myOptions);
// This is needed to set the zoom after fitbounds, 
google.maps.event.addListener(map, 'zoom_changed', function() {
    zoomChangeBoundsListener = 
        google.maps.event.addListener(map, 'bounds_changed', function(event) {
            if (this.getZoom() > 15 && this.initialZoom == true) {
                // Change max/min zoom here
                this.setZoom(15);
                this.initialZoom = false;
            }
        google.maps.event.removeListener(zoomChangeBoundsListener);
    });
});
map.initialZoom = true;
map.fitBounds(bounds);

Hoffentlich hilft das,

Anthony.

Malks
quelle
3
Dies ist eine gute Methode. Eine andere Methode besteht darin, die aktuellen Grenzen zu überprüfen und die Grenzen zu erweitern, dh stackoverflow.com/questions/3334729/… . Obwohl die verknüpfte Antwort hier nur die Grenzen um einen Bruchteil erweitert, können Sie dieselbe Methode verwenden, um die Grenzen um eine größere Zahl zu erweitern. Ich habe festgestellt, dass das Hinzufügen von 7 zu allen Ecken einen guten Job macht.
Metro Schlumpf
2
Ich möchte meinen vorherigen Kommentar korrigieren. Ich denke, dass das Festlegen der initialZoom-Eigenschaft erforderlich sein könnte. Ich hatte einige Probleme beim Zoomen in IE 9, nachdem ich diesen Teil des Codes weggelassen hatte ... Coole Lösung!
Andrew
21
Verwenden google.maps.event.addListenerOnce()Sie diese Option , damit Sie den Listener anschließend nicht manuell entfernen müssen.
Pstadler
5
Da ich mir das zum dritten Mal angesehen habe, ist hier die Golfversion. Danke @pstadler. google.maps.event.addListenerOnce(map, 'bounds_changed', function() { this.setZoom(Math.min(15, this.getZoom())); });
sba
1
Bei Verwendung von addLIstenerOnce können Sie einfach zuhören zoom_changed. Ich benutze zoom_changedkurz zuvor map.fitBounds(bounds);und scheint auf Chrome großartig zu funktionieren.
Milk Man
63

Ohne es zu versuchen, würde ich sagen, dass Sie in der Lage sein sollten, dies nur zu tun, fitBounds()bevor Sie die Zoomstufe erhalten, d. H.

map.fitBounds(bounds);
var zoom = map.getZoom();
map.setZoom(zoom > 6 ? 6 : zoom);

Wenn Sie das versucht haben und es nicht funktioniert hat, können Sie Ihre Karte mit minZoomin der MapOptions (API-Referenz) wie folgt einrichten :

var map = new google.maps.Map(document.getElementById("map"), { minZoom: 6 });

Dies würde verhindern, dass die Karte bei Verwendung weiter herauszoomt fitBounds().

Flygenring
quelle
schöne einfache und elegante Lösung!
Falantar014
3
Das Einstellen der Werte für minZoom und maxZoom hindert den Benutzer daran, über diese Werte hinaus zu zoomen. Es hilft also nicht, wenn Sie nur den anfänglichen Zoom auf einen vernünftigen Wert einstellen möchten (worüber ich denke, dass das OP gesprochen hat)
Izazael
5
Also im Grunde ziemlich genau so, wie ich es in meiner Antwort geschrieben habe?
Flygenring
@ Izazael macht einen guten Punkt, der in der Antwort nicht behandelt wird. Dies verhindert, dass das fitBounds()Zoomen zu weit geht, schränkt jedoch die Interaktion des Benutzers mit den Zoomschaltflächen der Karte ein. Die akzeptierte Antwort ist die bessere Option, wenn Sie es vorziehen, dass der Benutzer die volle Kontrolle hat.
Rich Court
1
Könnte nicht funktionieren, weil mit neuen Versionen. fitBounds () arbeitet asynchron!
RubbelDeCatc
19

Sie können die Option maxZoom auch unmittelbar vor dem Aufruf von fitBounds () festlegen und den Wert anschließend zurücksetzen:

if(!bounds.isEmpty()) {
    var originalMaxZoom = map.maxZoom;
    map.setOptions({maxZoom: 18});
    map.fitBounds(bounds);
    map.setOptions({maxZoom: originalMaxZoom});
}
Joost
quelle
Ich mag diese Option, weil sie nicht dazu führt, dass das zoom_changedEreignis wie viele andere Optionen zweimal ausgelöst wird
Greg
Tolle Lösung, wenn für das max-Objekt die Option maxZoom definiert ist.
Alexey Domanski
17

Anthonys Lösung ist sehr schön. Ich musste nur den Zoom für das Laden der ersten Seite korrigieren (um sicherzustellen, dass Sie nicht zu weit hineingezoomt haben), und dies hat den Trick für mich getan:

var zoomChangeBoundsListener =
    google.maps.event.addListener(map, 'bounds_changed', function(event) {
        google.maps.event.removeListener(zoomChangeBoundsListener);
        map.setZoom( Math.min( 15, map.getZoom() ) );
    });


map.fitBounds( zoomBounds );
Wütender Dan
quelle
5
Anstatt den Listener zu entfernen, können Sie ihn verwenden addListenerOnce, aber ich verwende diese Lösung.
Derek S
11

Wenn Sie map.fitBounds () für ein Element aufrufen, wird die Karte möglicherweise zu eng vergrößert. Um dies zu beheben, fügen Sie einfach 'maxZoom' zu mapOptions hinzu ...

var mapOptions = {
  maxZoom: 15
};
Mark Swardstrom
quelle
7

In meinem Fall wollte ich einfach die Zoomstufe auf eins weniger einstellen, als Google Maps bei fitBounds für mich ausgewählt hat. Der Zweck bestand darin, fitBounds zu verwenden, aber auch sicherzustellen, dass sich keine Markierungen unter Kartenwerkzeugen usw. befanden.

Meine Karte wird früh erstellt, und dann haben einige andere dynamische Komponenten der Seite die Möglichkeit, Markierungen hinzuzufügen und nach jeder Hinzufügung fitBounds aufzurufen.

Dies ist der erste Block, in dem das Kartenobjekt ursprünglich erstellt wurde ...

var mapZoom = null;

Dann wird dies zu jedem Block hinzugefügt, in dem ein Marker hinzugefügt wird, kurz bevor map.fitBounds aufgerufen wird ...

google.maps.event.addListenerOnce(map, 'bounds_changed', function() { 
    if (mapZoom != map.getZoom()) { 
        mapZoom = (map.getZoom() - 1); 
        map.setZoom(mapZoom); 
    } 
});

Bei Verwendung von 'bounds_changed' ohne das Einchecken wurde die Karte für jede Markierung einmal verkleinert, unabhängig davon, ob sie benötigt wurde oder nicht. Umgekehrt hatte ich bei Verwendung von 'zoom_changed' manchmal Markierungen unter den Kartenwerkzeugen, da sich der Zoom nicht wirklich geändert hat. Jetzt wird es immer ausgelöst, aber die Prüfung stellt sicher, dass es nur einmal und nur bei Bedarf herausgezoomt wird.

Hoffe das hilft.

oucil
quelle
Dies scheint die einzige Antwort zu sein, die tatsächlich verwendet addListenerwerden sollte, anstatt sie addListenerOncevor jedem einzelnen zu wiederholen (und sich darauf zu verlassen)map.fitBounds()
Flygenring
3

Da Google Maps V3 ereignisgesteuert ist, können Sie die API anweisen, den Zoom auf einen angemessenen Wert zurückzusetzen, wenn das Ereignis zoom_changed ausgelöst wird :

var initial = true
google.maps.event.addListener(map, "zoom_changed", function() {
    if (initial == true){
       if (map.getZoom() > 11) {
         map.setZoom(11);
         initial = false;
       }
    }
}); 

Ich habe initial verwendet , um die Karte nicht zu stark zu zoomen, wenn die eventuellen fitBounds durchlässig sind, sondern um den Benutzer so viel zoomen zu lassen, wie er möchte. Ohne die Bedingung wäre für den Benutzer ein Zoomereignis über 11 möglich.

abgestimmt
quelle
2

Ich fand das Folgende ganz gut. Es ist eine Variante auf Ryans Antwort auf https: //stackoverflow.com/questions/3334729 / ... . Es garantiert eine Fläche von mindestens dem Zweifachen des Wertes offsetin Grad.

const center = bounds.getCenter()
const offset = 0.01
const northEast = new google.maps.LatLng(
    center.lat() + offset,
    center.lng() + offset
)
const southWest = new google.maps.LatLng(
    center.lat() - offset,
    center.lng() - offset
)
const minBounds = new google.maps.LatLngBounds(southWest, northEast)
map.fitBounds(bounds.union(minBounds))
Jan K.
quelle