Frage

Ich habe eine Reihe von Punkten, die ich auf einer eingebetteten Google Map (API V3) zeichnen möchte. Ich möchte, dass die Grenzen alle Punkte aufnehmen, es sei denn, der Zoom -Level ist zu niedrig (dh zu viel herausgezoomt). Mein Ansatz war so:

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

// extend bounds with each point

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

Das funktioniert nicht. Die letzte Zeile "GMAP.SetZoom ()" ändert nicht die Zoompegel der Karte, wenn sie direkt nach Fitbounds aufgerufen werden.

Gibt es eine Möglichkeit, den Zoomniveau einer Grenzen zu erhalten, ohne sie auf die Karte anzuwenden? Andere Ideen, um dies zu lösen?

War es hilfreich?

Lösung

Bearbeiten: Siehe Matt Diamonds Kommentar unten.

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 Ihre Bedürfnisse.

Andere Tipps

Ich habe ein ähnliches Problem in einer meiner Apps gelöst. Ich war ein wenig verwirrt über Ihre Beschreibung des Problems, aber ich denke, Sie haben das gleiche Ziel, das ich hatte ...

In meiner App wollte ich eine oder mehrere Marker zeichnen und sicherstellen, dass die Karte sie alle anzeigt. Das Problem war, wenn ich mich ausschließlich auf die Fitbounds -Methode verließ, würde der Zoomebene maximal ausgelegt, wenn es einen einzelnen Punkt gab - das war nicht gut.

Die Lösung bestand darin, Fitbounds zu verwenden, wenn es viele Punkte gab, und SetCenter+Desszoom, wenn es nur einen Punkt gab.

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

Ich bin mehrmals auf diese Seite gekommen, um die Antwort zu erhalten, und obwohl alle vorhandenen Antworten super hilfreich waren, haben sie mein Problem nicht genau gelöst.

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

Grundsätzlich stellte ich fest, dass das Ereignis "Zoom_Changed" die Benutzeroberfläche der Karte daran hinderte, "überspringen" zu sein, was passiert war, als ich auf das "Idle" -Ereignis wartete.

Hoffe das hilft jemandem!

Ich habe dies gerade behoben, indem ich Maxzoom im Voraus festgelegt und dann danach entfernt habe. Zum Beispiel:

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

Wenn ich mich nicht irre, gehe ich davon aus, dass alle Ihre Punkte auf der Karte mit dem höchstmöglichen Zoom -Niveau sichtbar sind. Ich habe dies erreicht, indem ich die Zoomebene der Karte zu initialisierte 16(Ich bin mir nicht sicher, ob es das höchstmögliche Zoom -Level auf V3 ist).

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

Danach habe ich die Grenzen 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!

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

Dadurch wird der kleinere von 24 und die erforderliche Zoomebene gemäß Ihrem Code verwendet. Es ändert jedoch wahrscheinlich trotzdem den Zoom und kümmert sich nicht darum, wie viel Sie herausgegriffen haben.

Ich hatte das gleiche Problem und konnte es mit dem folgenden Code lösen. Dieser Zuhörer (google.maps.addListenerOnce()) Das Ereignis wird nur einmal entlassen, direkt danach map.fitBounds() wird ausgeführt. Es ist also nicht erforderlich

  1. Den Hörer verfolgen und manuell entfernen oder manuell entfernen, oder
  2. Warten Sie, bis die Karte ist idle.

Es legt zunächst die entsprechende Zoomebene fest und ermöglicht es dem Benutzer, die anfängliche Zoomebene zu vergrößern, da der Ereignishörer abgelaufen ist. Zum Beispiel nur, wenn nur google.maps.addListener() wurde gerufen, dann würde der Benutzer noch nie in der Lage sein, die angegebene Zoomebene zu verblassen (im Fall 4). Seit wir implementiert haben google.maps.addListenerOnce(), Der Benutzer wird in der Lage sein, auf jede Ebene zu zoomen, die er/sie wählt.

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

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

  1. Grenzen deklarieren
  2. Verwenden Sie das von Koderoid bereitgestellte Schema (für jeden Markersatz bounds.extend(objLatLng))
  3. Fitbounds führen, nachdem die Karte fertiggestellt wurde:

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

Ich habe eine Lösung gefunden, die vor dem Anruf die Überprüfung durchführt fitBounds Sie zoomen also nicht und zoomen plötzlich aus

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 mit der Minlatspan -Variablen ein wenig herumspielen, um sie dorthin zu bringen, wo Sie möchten. Es variiert sowohl auf Zoomebene als auch auf den Abmessungen der Karten-Leinwand.

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

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

Ich habe viele falsche oder zu komplizierte Lösungen gesehen und beschlossen, a zu posten Arbeiten, elegante Lösung.

Der Grund setZoom() funktioniert nicht so, wie Sie es erwarten, ist das fitBounds() ist asynchron, daher gibt es keine Garantie dafür, dass er den Zoom sofort aktualisiert, aber Ihr Anruf an setZoom() verlässt sich darauf.

Was Sie möglicherweise in Betracht ziehen, ist das Festlegen der minZoom MAP -Option, bevor Sie aufrufen fitBounds() Und dann räumen Sie es nach Abschluss (damit Benutzer immer noch manuell vergrößern 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 begrenzen möchten, können Sie den gleichen Trick mit dem anwenden maxZoom Eigentum.

Siehe das MAPOPTIONS DOCs.

Ich verwende dies, um sicherzustellen, dass die Zoomebene eine festgelegte Ebene nicht überschreitet, sodass ich weiß, dass Satellitenbilder verfügbar sein werden.

Fügen Sie dem einen Zuhörer zur zoom_changed Veranstaltung. Dies hat den zusätzlichen Vorteil, die Zoomsteuerung auch auf der Benutzeroberfläche zu kontrollieren.

Nur ausführen setZoom Wenn Sie müssen, also eine if Aussage ist vorzuziehen Math.max oder zu Math.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);

Um das Zoomen zu weit herauszugeben:

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

In dieser Funktion müssen Sie Metadaten dynamisch hinzufügen, um den Geometrie -Typ nur zu speichern, weil die Funktion eine 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);
},

Dies funktioniert für mich mit API V3, aber mit festem Zoom festgelegt:

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

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

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 streng gemäß Ihren Anforderungen wie diesem funktioniert:

    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 Sie anrufen map.fitLmtdBounds(bounds) Anstatt von map.fitBounds(bounds) um die Grenzen unter dem definierten Zoombereich einzustellen ... oder map.fitLmtdBounds(bounds,3,5) Um den Zoombereich zu überschreiben.

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 Ihnen hilfreich ist.

Alles Gute

Nach Berechnung der Grenzen können Sie den Abstand zwischen links und unten rechter Ecke überprüfen. Dann können Sie die Zoomebene verstehen, indem Sie den Abstand testen (wenn die Entfernung zu weit ist, wäre Zoompegel niedrig), dann können Sie die WHeter -Methode oder den Setbound -Methode oder den Desszoom auswählen.

Ich möchte es nicht gerne vorschlagen, aber wenn Sie muss Versuchen Sie - Erster Anruf

gmap.fitBounds(bounds);

Erstellen Sie dann einen neuen Thread/Asynctask, lassen Sie ihn ungefähr 20-50 ms schlafen und rufen Sie anschließend an

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

Aus dem UI -Thread (verwenden Sie einen Handler oder der onPostExecute Methode für Asynctask).

Ich weiß nicht, ob es funktioniert, nur ein Vorschlag. Ansonsten müssten Sie den Zoompegel selbst irgendwie selbst berechnen, prüfen Sie, ob es zu niedrig ist, korrigieren Sie es und rufen Sie dann einfach an gmap.setZoom(correctedZoom)

Wenn 'bounds_changed' nicht korrekt abgefeuert wird (manchmal scheint Google Koordinaten nicht perfekt zu akzeptieren), dann überlegen Sie stattdessen "Center_Changed".

Das Ereignis 'Center_Changed' feuert jedes Mal, wenn Fitbounds () aufgerufen wird, obwohl es sofort und nicht unbedingt nach dem Umzug der Karte ausgeführt wird.

In normalen Fällen ist "Idle" immer noch der beste Ereignishörer, aber dies kann ein paar Personen helfen, auf seltsame Probleme mit ihren Fitbounds () -Anrufen zu stoßen.

Sehen Google Maps Fitbounds Callback

Um mit einer anderen Lösung einzusteigen - ich fand, dass der Ansatz "Hören Sie für Bounds_Changed und dann neuer Zoom" nicht zuverlässig für mich. Ich glaube, ich habe manchmal angerufen fitBounds Bevor die Karte vollständig initialisiert wurde und die Initialisierung ein beschränktes Ereignis verursachte, das den Hörer zuvor verbrauchen würde fitBounds änderte die Grenzen und Zoomebene. Ich habe diesen Code gelandet, 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);
    });
  }
});

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

map.fitBounds(bounds);

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

Alles was ich getan habe ist:

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

Und es funktioniert auf V3 API.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top