google maps API 3 zooms out on fitBounds

前端 未结 7 1506
心在旅途
心在旅途 2021-01-11 14:48

I\'ve run into a problem where calling map.fitBounds seems to zoom out. I\'m trying to use the backbone.js router to save the map bounds in the url. I want to be able to boo

相关标签:
7条回答
  • 2021-01-11 15:24

    I noticed this behavior when using fitBounds() on a hidden map view (using a front-end rendering framework, like Angular). Because this was a mobile view, I was showing a list of locations first, and was populating the markers on a hidden map as the list was loading (a concurrent load). So when the user wants to view the map, and they switch the segment view/tab/whatever, the map would show with the markers already loaded and in view. But this bugged out and zoomed to show the complete world in the map.

    <div [hidden]="view !== 'map'>
        <google-map></google-map>
    </div>
    

    fitBounds() needs the map to be loaded in the view because it uses the maps dimensions in order to resize the map. If the map is hidden, it zooms the map until the complete map is shown.

    The solution was simple: when the view was switched, call fitBounds() again.

    <button (click)="showMap()">Show Map</button>
    
    public showMap() {
        this.view = 'map';
        setTimeout(() => {
            if (typeof this.map !== 'undefined') this.map.fitBounds(this.bounds);
        });
    }
    

    Note: I wrapped a setTimeout around the fitBounds() call so that Angular can finish the lifecycle and render the map before it is called.

    0 讨论(0)
  • 2021-01-11 15:25

    I noticed this problem too. My solution is to compare map.getBounds() to what I am setting the bounds to; if they are the same, I'm skipping the map.fitBounds() call.

    0 讨论(0)
  • 2021-01-11 15:29

    I was hit with the same problem and @Tomik's answer helped me resolving it. Here is the snippets of the code I used.

    To save the previous zoom and center.

    const lastMapZoom = this.map.getZoom();
    const lastMapCenter = this.map.getCenter();
    

    To set the values back.

    this.map.setCenter(lastMapZoom);
    this.map.setZoom(lastMapCenter);
    
    0 讨论(0)
  • 2021-01-11 15:31

    For people seeing this question in 2018, Google Maps API v3 now supports a second padding argument that specifies the amount of padding to include around the bounds you specify.

    To avoid zooming out, simply just call fitBounds with a padding of 0. For this example it would be map.fitBounds(map.getBounds(), 0)

    0 讨论(0)
  • 2021-01-11 15:31

    Fixing this problem in 2017

    Shrink the bounding box slightly before sending it to map.fitBounds().

    Here's a function to shrink a bounding box:

    // Values between 0.08 and 0.28 seem to work
    // Any lower and the map will zoom out too much
    // Any higher and it will zoom in too much
    var BOUNDS_SHRINK_PERCENTAGE = 0.08; // 8%
    
    /**
     * @param  {google.maps.LatLngLiteral} southwest
     * @param  {google.maps.LatLngLiteral} northeast
     * @return {Array[google.maps.LatLngLiteral]}
     */
    function slightlySmallerBounds(southwest, northeast) {
      function adjustmentAmount(value1, value2) {
        return Math.abs(value1 - value2) * BOUNDS_SHRINK_PERCENTAGE;
      }
    
      var latAdjustment = adjustmentAmount(northeast.lat, southwest.lat);
      var lngAdjustment = adjustmentAmount(northeast.lng, southwest.lng);
    
      return [
        {lat: southwest.lat + latAdjustment, lng: southwest.lng + lngAdjustment},
        {lat: northeast.lat - latAdjustment, lng: northeast.lng - lngAdjustment}
      ]
    }
    

    Use it like this:

    // Ensure `southwest` and `northwest` are objects in google.maps.LatLngLiteral form:
    // southwest == {lat: 32.79712, lng: -117.13931}
    // northwest == {lat: 32.85020, lng: -117.09356}
    
    var shrunkBounds = slightlySmallerBounds(southwest, northeast);
    var newSouthwest = shrunkBounds[0];
    var newNortheast = shrunkBounds[1];
    
    // `map` is a `google.maps.Map`
    map.fitBounds(
      new google.maps.LatLngBounds(newSouthwest, newNortheast)
    );
    

    I have an app doing the same thing as codr: saving the current map bounds in the URL, and initializing the map from the URL bounds upon refresh. This solution works wonderfully for that.

    Why does this work?

    Google Maps essentially does this when fitBounds() is called:

    1. Center the map on the centerpoint of the given bounding box.
    2. Zoom in to the highest zoom level where the viewport would contain the given bounds inside of the viewport box.

    If the bounds given would exactly match the viewport, Google Maps doesn't consider that as "containing" the bounds, so it zooms out one more level.

    0 讨论(0)
  • 2021-01-11 15:33

    This problem of Google Map API was discussed few times. See:

    • gmaps-api-issues
    • google-maps-js-api-v3 group

    Function map.fitBounds() sets the viewport to contain the bounds. But map.getBounds() function returns the viewport bounds with some extra margin (note that this is normal behaviour and no bug). The enlarged bounds no longer fits in the previous viewport, so the map zooms out.

    A simple solution to your problem is to use the map center and the zoom level instead. See functions map.getCenter(), map.setCenter(), map.getZoom() and map.setZoom().

    0 讨论(0)
提交回复
热议问题