Google Maps v3 fitBounds() Zoom too close for single marker

前端 未结 17 2070
别那么骄傲
别那么骄傲 2020-12-12 23:28

Is there a way to set a max zoom level for fitBounds()? My problem is that when the map is only fed one location, it zooms in as far as it can go, which really

相关标签:
17条回答
  • 2020-12-12 23:43

    Here is my go at a solution, which also works when two markers are very close. The effective maximum zoom level is the same in both situations. So we do not end up zooming unneccesarily out, when there are more than one marker

    The effect, again is ensuring a maximum zoom, without using the maxZoom option, which has the probably unwanted effect of making it impossible for the user to zoom further than the maxZoom level with the zoom control

    I have calculated maxLat, minLat, maxLng and minLng beforehand...

    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,
    });
    
    0 讨论(0)
  • 2020-12-12 23:47

    If it is for a single location, you can use setCenter() and setZoom() instead.

    0 讨论(0)
  • 2020-12-12 23:47

    I really like mrt's solution and it works perfectly if you've always only have one point to work with. I did however find that if the bounding box was not based on one point, but the points were very close together, this could still cause the map to be zoomed in too far.

    Here's a way to first check if the points are within a defined distance of each other, then if they are smaller than that minimum distance, extend the bounds by that minimum distance:

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

    Hope this helps someone!

    0 讨论(0)
  • 2020-12-12 23:47

    And .. here is another one.
    Same idea as mrt and Ryan, but

    • also works if bounds size is not exactly zero (*)
    • prevents distortion near the poles
    • uses getCenter() instead of getNorthEast()

    (*) Note: If the box is already big enough, then adding those two extra points should have no effect. So we don't need any further checking.

    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: I am not exactly sure if my ratio calculation correctly, considering we have a Mercator projection. I might re-edit this..

    0 讨论(0)
  • 2020-12-12 23:47

    Its already answered here Google Maps v3: Enforcing min. zoom level when using fitBounds it works as expected :) so now if after fit bounds zoom is less then lets say 13 then you can set new zoom which you preffer

    0 讨论(0)
  • 2020-12-12 23:49

    I like mrt's solution (especially when you don't know how many points you will be mapping or adjusting for), except it throws the marker off so that it isn't in the center of the map anymore. I simply extended it by an additional point subtracting .01 from the lat and lng as well, so it keeps the marker in the center. Works great, thanks 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 :/
    
    }
    
    0 讨论(0)
提交回复
热议问题