Google Maps v3 fitBounds () Zoom für einen einzelnen Marker zu nah

92

Gibt es eine Möglichkeit, eine maximale Zoomstufe für festzulegen fitBounds()? Mein Problem ist, dass wenn die Karte nur an einem Ort gespeist wird, sie so weit wie möglich vergrößert wird, wodurch die Karte wirklich aus dem Kontext gerissen und unbrauchbar wird. Vielleicht gehe ich falsch vor?

Danke im Voraus!

Codey W.
quelle
2
stackoverflow.com/questions/4523023/… ist eine viel bessere Lösung. Besondere @ Nequins Antwort
Kennet

Antworten:

137

Ich mag die Lösung von mrt (besonders wenn Sie nicht wissen, wie viele Punkte Sie zuordnen oder anpassen werden), außer dass sie den Marker abwirft, sodass er nicht mehr in der Mitte der Karte liegt. Ich habe es einfach um einen zusätzlichen Punkt erweitert, der auch 0,01 von lat und lng subtrahiert, damit der Marker in der Mitte bleibt. Funktioniert super, danke mrt!

// Pan & Zoom map to show all markers
function fitToMarkers(markers) {

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

    // Create bounds from markers
    for( var index in markers ) {
        var latlng = markers[index].getPosition();
        bounds.extend(latlng);
    }

    // Don't zoom in too far on only one marker
    if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
       var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.01, bounds.getNorthEast().lng() + 0.01);
       var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - 0.01, bounds.getNorthEast().lng() - 0.01);
       bounds.extend(extendPoint1);
       bounds.extend(extendPoint2);
    }

    map.fitBounds(bounds);

    // Adjusting zoom here doesn't work :/

}
Ryan
quelle
4
Gute Idee, das ursprüngliche Zentrum beizubehalten. Der Grund, warum die Zoomstufe bei Verwendung der fitBounds()Methode nicht zuverlässig angepasst werden kann , ist, dass der Zoom asynchron erfolgt: stackoverflow.com/questions/2989858/…
Metro Smurf
1
Das hat bei mir super funktioniert. Ich musste die Kartenreferenz in die Funktion "function fitToMarkers (marker, map)" auf V3 übergeben, aber danach funktioniert es wie ein Zauber!
Shane
4
Ich mag das. Guter @ryan. Hat für mich großartig funktioniert, aber .01 in meinem Fall hat zu weit herausgezoomt, .001 hat den Sweet Spot erreicht.
Willdanceforfun
Vielen Dank. Wie bei @willdanceforfun im gleichen Fall traf 001 genau das Richtige.
Goran Jakovljevic
1
Ich würde diese Lösung empfehlen stackoverflow.com/questions/2437683/…
NinjaOnSafari
37

Sie können Ihre Karte mit maxZoomin der MapOptions (API-Referenz) wie folgt einrichten :

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

Dies würde verhindern, dass die Karte bei Verwendung tiefer zoomt, fitBounds()und sogar die Zoomstufen aus der Zoomsteuerung entfernen.

Flygenring
quelle
@ Candlejack Also genau wie in meiner Antwort beschrieben?
Flygenring
6
Sie können das festlegen, maxZoombevor Sie die Grenzen anpassen, und es dann erneut deaktivieren, indem Sie map.setOptions({ maxZoom: undefined })das idleEreignis verwenden, indem Sie die Grenzen ändern. Dies verhindert das Vergrößern und Verkleinern, indem stattdessen das Vergrößern des idleEreignisses zurückgesetzt wird.
El Yobo
29

Eine andere Lösung besteht darin, Grenzen zu erweitern, wenn Sie feststellen, dass sie zu klein sind, bevor Sie fitBounds () ausführen:

var bounds = new google.maps.LatLngBounds();
// here you extend your bound as you like
// ...
if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
   var extendPoint = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.01, bounds.getNorthEast().lng() + 0.01);
   bounds.extend(extendPoint);
}
map.fitBounds(bounds);
mrt
quelle
19
var map = new google.maps.Map(document.getElementById("map"), { maxZoom: 10 });

Die Verwendung der MaxZoom-Option funktioniert am besten, wenn Sie nicht zoomen, um sich den Markierungen zu nähern, die Sie haben.

markvaneijk
quelle
Fantastisch! Lebensretter!
Jaypee
18

Sobald Sie alle realen Grenzen hinzugefügt haben, fügen Sie diese Linien hinzu

var offset = 0.002;     
var center = bounds.getCenter();                            
bounds.extend(new google.maps.LatLng(center.lat() + offset, center.lng() + offset));
bounds.extend(new google.maps.LatLng(center.lat() - offset, center.lng() - offset));

Es erhält das Zentrum der realen Grenzen und fügt dann zwei zusätzliche Punkte hinzu, einen im Nordosten und einen im Südwesten Ihres Zentrums

Dadurch wird der minimale Zoom effektiv eingestellt und der Versatzwert geändert, um den Zoom zu erhöhen oder zu verringern

PWHIT
quelle
12

Wenn es sich um einen einzelnen Speicherort handelt, können Sie stattdessen setCenter () und setZoom () verwenden.

CrazyEnigma
quelle
einfachste Lösung
Alberto M
11

du kannst benutzen

map.setOptions({
    maxZoom: [what u want],
    minZoom: [what u want]
});

Auf diese Weise legen Sie die Eigenschaften der Karte fest, nachdem die Karte initialisiert wurde. Sie können sie so oft festlegen, wie Sie möchten. In Ihrem Fall können Sie sie jedoch vor fitBounds () festlegen.

Viel Glück, Rarutu

Wowzaaa
quelle
7

Ich verhindere, dass die Karte zu weit vergrößert wird, indem ich folgende Codezeile hinzufüge:

var zoomOverride = map.getZoom();
        if(zoomOverride > 15) {
        zoomOverride = 15;
        }
      map.setZoom(zoomOverride);

Direkt nach dieser Zeile:

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

Sie können die Zoomstufe jederzeit auf die Stufe ändern, an der die Karte nicht vorbeizoomen soll.

Wenn Sie Probleme oder Fragen haben, hinterlassen Sie mir einfach einen Kommentar zu dem Blog-Beitrag, den ich dazu unter http://icode4you.net/creating-your-own-store-locator-map-how-to-prevent-the- geschrieben habe. Karte-vom-Zoomen-zu-nah-auf-einen-einzelnen-Marker

TheLibzter
quelle
1
Ich mag diese Lösung, aber füge den Setzoom in das if ein, um ihn nicht jedes Mal aufzurufen. Es könnte auch einen Timing-Nebeneffekt geben, der 'undefined' von getzoom () zurückgibt. Lösung: zoom = map.getZoom (); if (Zoomart! == 'undefiniert' && Zoom> 8) map.setZoom (8);
Le Droid
5

Ich mag die Lösung von mrt sehr und sie funktioniert perfekt, wenn Sie immer nur einen Punkt haben, mit dem Sie arbeiten können. Ich habe jedoch festgestellt, dass, wenn der Begrenzungsrahmen nicht auf einem Punkt basiert, die Punkte jedoch sehr nahe beieinander liegen, die Karte dennoch zu weit vergrößert werden kann.

Hier erfahren Sie zunächst, ob die Punkte innerhalb eines definierten Abstands voneinander liegen. Wenn sie dann kleiner als dieser Mindestabstand sind, erweitern Sie die Grenzen um diesen Mindestabstand:

var bounds = new google.maps.LatLngBounds();
// here you extend your bound as you like

// ...

var minDistance = 0.002;
var sumA = bounds.getNorthEast().lng() - bounds.getSouthWest().lng();
var sumB = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();

if((sumA < minDistance && sumA > -minDistance) 
&& (sumB < minDistance && sumB > -minDistance)){
var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + minDistance, bounds.getNorthEast().lng() + minDistance);
    var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - minDistance, bounds.getNorthEast().lng() - minDistance);
    bounds.extend(extendPoint1);
    bounds.extend(extendPoint2);
}

Hoffe das hilft jemandem!

Pakage
quelle
3

Dies gibt Ihnen eine direkte Kontrolle über die maximal zulässige Vergrößerung der Grenzen.

var fitToMarkers = function(map, markers, maxZoom) {
    if (typeof maxZoom == 'undefined') maxZoom = 15;

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

    var bounds = new google.maps.LatLngBounds();
    for (var m = 0; m < markers.length; m++) {
        var marker = markers[m];
        var latlng = marker.getPosition();
        bounds.extend(latlng);
    }

    map.fitBounds(bounds);
};
Klima
quelle
3

Was mich betrifft, löse ich es, indem ich nach fitBounds ein Leerlaufereignis erstelle. Perfekt funktionieren. Ich denke, das ist eine der saubersten Lösungen hier

var locations = [['loc', lat, lng], ['loc', lat, lng]];
.....
for (i = 0; i < locations.length; i++) { 
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 10
  });
  .... create markers, etc.
}
....
map.fitBounds(bounds);  
google.maps.event.addListenerOnce(map, 'idle', function() {
  if (locations.length == 1) {
    map.setZoom(11);
  }
});
Vitali Protosovitski
quelle
2

Ich habe mit diesem Block gelöst, da Google Maps V3 ereignisgesteuert ist:

Sie können 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 (intial == true){
       if (map.getZoom() > 11) {
         map.setZoom(11);
         intial = false;
       }
    }
}); 

Ich habe anfänglich dafür gesorgt, dass die Karte nicht zu stark gezoomt wird, wenn die eventuellen fitBounds durchlässig sind. Ohne sie wäre ein Zoomereignis über 11 für den Benutzer unmöglich.

abgestimmt
quelle
1

fitBounds()Versuchen Sie nach dem Aufrufen der Methode erneut, die Zoomstufe einzurichten. Dadurch wird die Karte auf diese Zoomstufe gebracht, während sie an der richtigen Stelle zentriert ist.

moneshchary
quelle
0

Ich habe eine Soulution basierend auf der Begrenzung des maximalen Zooms beim Anpassen von Grenzen. Funktioniert für mich (getestet unter Win 7 - IE 9, FF 13, Chrome 19):

// When fitting bounds:
var bounds = new google.maps.LatLngBounds();
// ...
// extend bounds as you like
// ..

// now set global variable when fitting bounds
window.fittingBounds = true;
map.fitBounds(bounds);
window.fittingBounds = false;


// attach this event listener after map init
google.maps.event.addListener(map, 'zoom_changed', function() {
    // set max zoom only when fitting bounds
    if (window.fittingBounds && map.getZoom() > 16) {
        this.setZoom(16);
    }
});
Muffir
quelle
0

Und ... hier ist noch einer.
Gleiche Idee wie Herr und Ryan, aber

  • funktioniert auch, wenn die Grenzgröße nicht genau Null ist (*)
  • verhindert Verzerrungen in der Nähe der Pole
  • verwendet getCenter () anstelle von getNorthEast ()

(*) Hinweis: Wenn die Box bereits groß genug ist, sollte das Hinzufügen dieser beiden zusätzlichen Punkte keine Auswirkung haben. Wir brauchen also keine weitere Überprüfung.

function calcBounds(markers) {
  // bounds that contain all markers
  var bounds = new google.maps.LatLngBounds();
  // Using an underscore _.each(). Feel free to replace with standard for()
  _.each(markers, function(marker) {
    bounds.extend(marker.getPosition());
  });
  // prevent lat/lng distortion at the poles
  var lng0 = bounds.getNorthEast().lng();
  var lng1 = bounds.getSouthWest().lng();
  if (lng0 * lng1 < 0) {
    // Take the cos at the equator.
    var cos = 1;
  }
  else {
    var cos0 = Math.cos(lng0);
    var cos1 = Math.cos(lng1);
    // Prevent division by zero if the marker is exactly at the pole.
    var cos_safe = Math.max(cos0, cos1, 0.0001);
  }
  var cos0 = Math.cos(bounds.getNorthEast.lng() * Math.PI / 180);
  var cos1 = Math.cos(bounds.getSouthWest.lng() * Math.PI / 180);
  // "radius" in either direction.
  // 0.0006 seems to be an ok value for a typical city.
  // Feel free to make this value a function argument.
  var rLat = 0.0006;
  var rLng = rLat / cos_safe;
  // expand the bounds to a minimum width and height
  var center = bounds.getCenter();
  var p0 = new google.maps.LatLng(center.lat() - rLat, center.lng() - rLng);
  var p1 = new google.maps.LatLng(lat.center() + rLat, center.lng() + rLng);
  bounds.extend(p0);
  bounds.extend(p1);
  return bounds;
}

EDIT: Ich bin nicht genau sicher, ob meine Verhältnisberechnung korrekt ist, wenn man bedenkt, dass wir eine Mercator-Projektion haben. Ich könnte dies erneut bearbeiten.

Donquijote
quelle
-1

Hier ist meine Lösung, die auch funktioniert, wenn zwei Marker sehr nahe beieinander liegen. Die effektive maximale Zoomstufe ist in beiden Situationen gleich. Wir werden also nicht unnötig herauszoomen, wenn mehr als eine Markierung vorhanden ist

Der Effekt sorgt wiederum für einen maximalen Zoom, ohne die Option maxZoom zu verwenden. Dies hat den wahrscheinlich unerwünschten Effekt, dass der Benutzer mit der Zoomsteuerung nicht weiter als bis zur maxZoom-Stufe zoomen kann

Ich habe vorher maxLat, minLat, maxLng und minLng berechnet ...

var minLatSpan = 0.002;
if (maxLat - minLat < minLatSpan) {
  // ensures that we do not zoom in too much
  var delta = (minLatSpan - (maxLat - minLat)) / 2;
  maxLat += delta;
  minLat -= delta;
}

map.fitBounds({
  east: maxLng,
  west: minLng,
  north: maxLat,
  south: minLat,
});
rosell.dk
quelle