it-swarm.com.de

Google Maps API v3: Kann ich Zoom nach fitBounds setzen?

Ich habe eine Reihe von Punkten, die ich in eine eingebettete Google Map (API v3) zeichnen möchte. Ich möchte, dass die Begrenzungen alle Punkte aufnehmen, es sei denn, die Zoomstufe ist zu niedrig (d. H. Zu stark herausgezoomt). Mein Ansatz war wie folgt:

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

// extend bounds with each point

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

Das geht nicht. Die letzte Zeile "gmap.setZoom ()" ändert den Zoomfaktor der Karte nicht, wenn sie direkt nach fitBounds aufgerufen wird.

Gibt es eine Möglichkeit, die Zoomstufe einer Begrenzung zu ermitteln, ohne sie auf die Karte anzuwenden? Andere Ideen, um das zu lösen?

191
chris

Bearbeiten : Siehe den Kommentar von Matt Diamond.

Ich habs! Versuche dies:

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

Ändern Sie nach Ihren Bedürfnissen.

319
LGT

Ich habe ein ähnliches Problem in einer meiner Apps gelöst. Ich war etwas verwirrt von Ihrer Beschreibung des Problems, aber ich denke, Sie haben dasselbe Ziel wie ich ...

In meiner App wollte ich einen oder mehrere Marker zeichnen und sicherstellen, dass die Karte alle anzeigt. Das Problem war, wenn ich mich ausschließlich auf die fitBounds-Methode stützte, würde die Zoom-Ebene bei einem einzigen Punkt maximal sein - das war nicht gut.

Die Lösung bestand darin, fitBounds zu verwenden, wenn viele Punkte vorhanden waren, und setCenter + setZoom, wenn es nur einen Punkt gab.

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

Ich bin mehrmals auf diese Seite gekommen, um die Antwort zu erhalten, und obwohl alle vorhandenen Antworten sehr hilfreich waren, lösten sie mein Problem nicht genau. 

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

Grundsätzlich habe ich festgestellt, dass das Ereignis 'zoom_changed' verhindert hat, dass die Benutzeroberfläche der Karte "überspringt", was passiert ist, als ich auf das Ereignis 'Leerlauf' wartete.

Hoffe das hilft jemandem!

43

Ich habe das Problem behoben, indem Sie maxZoom vorab eingestellt und anschließend entfernt haben. Zum Beispiel:

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

Wenn ich mich nicht irre, nehme ich an, Sie möchten, dass alle Punkte auf der Karte mit der höchstmöglichen Zoomstufe sichtbar sind. Ich habe dies erreicht, indem ich die Zoomstufe der Karte auf 16 initialisiert habe (nicht sicher, ob es sich bei V3 um die höchstmögliche Zoomstufe handelt). 

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

Danach habe ich die Sachen gemacht:

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);

Ergebnis: Erfolg!

4
Lester S

Ich benutze:

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

Dies wird die kleinere von 24 und die erforderliche Zoomstufe entsprechend Ihrem Code verwenden, ändert jedoch wahrscheinlich den Zoom trotzdem und kümmert sich nicht darum, wie viel Sie herausgezoomt haben.

3
ytg

Bitte versuchen Sie das:

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
Atif Tariq

Hatte das gleiche Problem, musste viele Marker auf die Karte passen ..__ Dies löste meinen Fall:

  1. Grenzen erklären 
  2. Verwenden Sie das von koderoid bereitgestellte Schema (für jeden Markierungssatz bounds.extend(objLatLng)).
  3. Führe fitbounds aus, nachdem die Map abgeschlossen ist:

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

Ich habe eine Lösung gefunden, die die Überprüfung vor dem Aufruf von fitBounds durchführt, damit Sie nicht hineinzoomen und plötzlich herauszoomen

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);
}

Sie müssen ein wenig mit der Variablen minLatSpan herumspielen, um sie an die gewünschte Stelle zu bringen. Sie hängt von der Zoomstufe und den Abmessungen des Kartenbereichs ab. 

Sie können auch Längengrad anstelle von Breitengrad verwenden

2
CheapSteaks

diese Arbeit ist für mich mit API v3, aber mit festem Zoom:

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

gmap.setCenter(bounds.getCenter()); 
gmap.setZoom( 6 );
1
Pedro Blaszczak

Ich hatte das gleiche Problem und konnte es mit dem folgenden Code lösen. Dieses Listener (google.maps.addListenerOnce()) -Ereignis wird nur einmal ausgelöst, unmittelbar nachdem map.fitBounds() ausgeführt wurde. Es besteht also keine Notwendigkeit 

  1. Behalten Sie den Listener oder entfernen Sie ihn manuell 
  2. Warten Sie, bis die Karte idle ist.

Zunächst wird die entsprechende Zoomstufe festgelegt, und der Benutzer kann über die ursprüngliche Zoomstufe hinaus zoomen, da der Ereignislistener abgelaufen ist. Wenn beispielsweise nur google.maps.addListener() aufgerufen wurde, würde dies der Benutzer tun noch nie über die angegebene Zoomstufe hinaus zoomen können (in dem Fall 4). Seit wir google.maps.addListenerOnce() implementiert haben, kann der Benutzer auf jede gewünschte Ebene zoomen.

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) 
   }
});
1
9monkeys

Wenn Sie nicht bereit sind, mit Zuhörern zu spielen, ist dies eine einfache Lösung, die ich mir ausgedacht habe: Fügen Sie eine Methode auf der Karte hinzu, die genau Ihren Anforderungen entspricht, wie dieser:

    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});
    }

dann können Siemap.fitLmtdBounds(bounds)anstelle von map.fitBounds(bounds) aufrufen, um die Grenzen unter dem definierten Zoombereich festzulegen ... odermap.fitLmtdBounds(bounds,3,5), um den Zoombereich zu überschreiben.

1
Kanak Singhal

Ich habe viele falsche oder zu komplizierte Lösungen gesehen, also habe ich beschlossen, eine funktionierende, elegante Lösung zu posten.

Der Grund dafür, dass setZoom() nicht wie erwartet funktioniert, ist, dass fitBounds() asynchron ist. Daher kann nicht garantiert werden, dass der Zoom sofort aktualisiert wird. Der Aufruf von setZoom() hängt jedoch davon ab.

Sie sollten in Betracht ziehen, die minZoom map -Option vor dem Aufruf von fitBounds() einzustellen und sie anschließend zu löschen, nachdem sie abgeschlossen ist (damit Benutzer weiterhin manuell verkleinern können, wenn sie möchten):

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);

Wenn Sie auch den maximalen Zoom einschränken möchten, können Sie denselben Trick mit der maxZoom -Eigenschaft anwenden.

Siehe MapOptions-Dokumente .

1
Svilen Marchev

In dieser Funktion müssen Sie Metadaten dynamisch hinzufügen, um nur den Geometrietyp zu speichern, da die Funktion beliebige Geometrie akzeptiert.

"fitGeometries" ist eine JSON-Funktion, die ein Kartenobjekt erweitert.

"Geometrien" ist ein generisches Javascript-Array, kein MVCArray ().

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);
},
1
CrazyEnigma

Ich verwende dies, um sicherzustellen, dass die Zoomstufe eine festgelegte Stufe nicht überschreitet, so dass ich weiß, dass Satellitenbilder verfügbar sind.

Fügen Sie dem zoom_changed-Ereignis einen Listener hinzu. Dies hat den zusätzlichen Vorteil, dass auch die Zoomsteuerung auf der Benutzeroberfläche gesteuert wird.

Führen Sie setZoom nur aus, wenn dies erforderlich ist, daher ist eine if-Anweisung Math.max oder Math.min vorzuziehen.

   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);

So verhindern Sie ein Herauszoomen:

   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
Mantis

Wenn 'bounds_changed' nicht korrekt ausgelöst wird (manchmal scheint Google Koordinaten nicht perfekt zu akzeptieren), sollten Sie stattdessen 'center_changed' verwenden. 

Das 'center_changed' Ereignis wird bei jedem Aufruf von fitBounds () ausgelöst, obwohl es sofort ausgeführt wird und nicht unbedingt, nachdem die Karte verschoben wurde. 

Im Normalfall ist "Leerlauf" immer noch der beste Ereignis-Listener. Dies kann jedoch hilfreich sein, wenn ein paar Personen mit ihren fitBounds () - Aufrufen auf seltsame Probleme stoßen. 

google maps fitBounds callback

0
tempranova

Nach der Berechnung der Grenzen können Sie den Abstand zwischen der oberen linken und der rechten unteren Ecke überprüfen. dann können Sie die Zoomstufe verstehen, indem Sie die Entfernung testen (wenn die Entfernung zu groß ist, würde die Zoomstufe zu niedrig sein). Dann können Sie auswählen, ob Sie die Methode setbound oder setZoom verwenden.

0
Orhun Alp Oral

Für mich war die einfachste Lösung folgende:

map.fitBounds(bounds);

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

Ich schlage es nicht gerne vor, aber wenn Sie müssen versuchen - zuerst anrufen

gmap.fitBounds(bounds);

Dann erstelle einen neuen Thread/AsyncTask, lasse ihn für 20-50ms oder so schlafen und rufe dann an

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

aus dem UI-Thread (verwenden Sie einen Handler oder die Methode onPostExecute für AsyncTask).

Ich weiß nicht, ob es funktioniert, nur ein Vorschlag. Ansonsten müsstest du die Zoomstufe aus deinen Punkten irgendwie selbst berechnen, prüfen, ob sie zu niedrig ist, korrigieren und dann einfach gmap.setZoom(correctedZoom) aufrufen

0
Joseph Earl

Bitte versuchen Sie das.

// 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);
}

Wenn dies hilfreich für Sie ist.

Alles Gute

0
Kanak Vaghela

Um mit einer anderen Lösung zu spielen, habe ich festgestellt, dass der Ansatz "Hören auf bounds_changed und dann neuen Zoom einstellen" für mich nicht zuverlässig funktioniert. Ich denke, dass ich manchmal fitBounds angerufen habe, bevor die Karte vollständig initialisiert wurde, und dass die Initialisierung ein bounds_changed -Ereignis verursachte, das den Listener verbrauchte, bevor fitBounds die Grenzen und die Zoomstufe änderte. Ich endete mit diesem Code, der bisher zu funktionieren scheint:

// 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
philh