Google Maps API V3 fitbounds() zooms out but never in

前端 未结 12 2374
感动是毒
感动是毒 2020-12-19 03:44

I\'ve created a quite complex store locator of sorts. The user enters their zip and a table returns results with corresponding markers on a map. They can page through result

相关标签:
12条回答
  • 2020-12-19 03:46

    Hmm, interesting.. I use PHP to loop through all (to be) marker coordinates and calculate the values of southWest and northEast; the coords of origin are halfway between the two. If all marker coordinates are very close to each other, the zoom factor set by fitBounds is much higher (zoomed in) than the 15 used at map creation. That's why I have added that last row..

    var map;
    
    function mapInit() {
      var origin = new google.maps.LatLng(59.33344615, 18.0678188);
      var options = {
        zoom: 15,
        center: origin,
        mapTypeControlOptions: {
          mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.HYBRID]
        },
        mapTypeId: google.maps.MapTypeId.ROADMAP
      };
    
      map = new google.maps.Map(document.getElementById("googlemap"), options);
    
      var southWest = new google.maps.LatLng(59.3308415, 18.0643054);
      var northEast = new google.maps.LatLng(59.3360508, 18.0713322);
      var bounds = new google.maps.LatLngBounds(southWest, northEast);
      map.fitBounds(bounds);
    
      google.maps.event.addListenerOnce(map, "idle", function() {
        if (map.getZoom() > 16) map.setZoom(16);
      });
    

    So, either Google has reprogrammed the function since you posted the question or.. I need more information about your code.

    0 讨论(0)
  • 2020-12-19 03:47

    I encountered this general problem today, thought I'd share a solution. I realise this is slightly different to your 'store locator' problem, but it does apply in many ways. In my case I have a collection of markers on the map and am adding one, and want to ensure all markers are now in view. This code checks each existing marker to see if its in the view, and along the way, builds a new bounding box that would contain them all, if required. At the end, if any have been found to not be in view, the view is reset so they all are.

    (this uses Dojo's array module, simply a convenience wrapper around basic array iteration)

    var origBounds = map.getBounds(),
        newBounds = new google.maps.LatLngBounds(null),
        anyFailed = false;
    array.forEach(markers, function (m) {
        newBounds.extend(m.position);
        if (!origBounds.contains(m.position)) {
            anyFailed = true;
        }
    });
    if (anyFailed) {
        map.setCenter(newBounds.getCenter());
        map.fitBounds(newBounds);
    }
    

    One could easily modify this to only ensure the new marker is in view, by not looping and just doing a contains() check on the new marker.

    0 讨论(0)
  • 2020-12-19 03:48

    Check this quote from the GMap docs on marker.setMap(null); (which is used for removing markers from a map):

    Note that the above method does not delete the marker. It removes the marker from the map. If instead you wish to delete the marker, you should remove it from the map, and then set the marker itself to null.

    My problem was that when I was removing markers from the map they were still stored in map.markers. So when setting bounds it is grabbing all previous markers also:

    map.markers.forEach( (marker) => {
      var latlng = new google.maps.LatLng(marker.position.lat(), marker.position.lng())
      bounds.extend(latlng)
    })
    

    Console.logging bounds showed that the bounds would always accommodate all earlier bounds because of this.

    My solution was to keep track of the markers in a seperate markers array/object that stores a unique key for each marker (in my case linked to a places autocomplete input field) and remove a marker from it when removing the marker from a map. This way I can run a check when generating bounds to see if the current marker in map.markers is in the (up-to-date) markers array.

    map.markers.forEach( (marker) => {
      // check if map marker is in this.markers (to make sure only current)
      for (const [key, value] of Object.entries(markers)) {
        if (marker == value) {
          var latlng = new google.maps.LatLng(marker.position.lat(), marker.position.lng())
          bounds.extend(latlng)
        }
      }
    })
    

    Now my map zooms in correctly after changing the markers. If anyone can come up with any improvements to above method I would love to hear it!

    Rens

    0 讨论(0)
  • 2020-12-19 03:49
    map.setZoom(10);
    

    I believe the acceptable range is 1-20. Whole numbers only, decimals broke the map in my experience.

    0 讨论(0)
  • 2020-12-19 03:50

    It turns out that when you call map.getBounds() it returns the viewport with a little margin around the edges. Since this new bounds is larger than the current bounds, the map will always zoom out. I was able to solve it by avoiding using the current map's bounds altogether and maintaining a separate LatLngBounds variable. Every time I added a point I called:

    markersBounds.extend(newMarkersLatLng);
    map.fitBounds(markersBounds);
    map.panToBounds(markersBounds);
    

    To remove points (I was always adding them), you could make a new LatLngBounds object with the first point, then extend each remaining point to get your new bounds:

    var markersBounds = new google.maps.LatLngBounds(markers[0].getPosition(),
                                                     markers[0].getPosition());
    for(var i=1; i<markers.length; i++){
        markersBounds.extend(markers[i].getPosition());
    }
    
    map.fitBounds(markersBounds);
    map.panToBounds(markersBounds);
    
    0 讨论(0)
  • 2020-12-19 03:52

    What helped me was using 0 padding as the second parameter to fitBounds(bounds, padding), here is the full code sample:

    function initMap() {
        var mapOptions = {
            center: new google.maps.LatLng(0, 0),
            zoom: 1,
            minZoom: 1
        };
        map = new google.maps.Map(document.getElementById('officeMap'), mapOptions);
        google.maps.event.addListenerOnce(map, 'idle', function() {
            //Map is ready
            worldViewFit(map);
        });
    }
    function worldViewFit(mapObj) {
        var worldBounds = new google.maps.LatLngBounds(
            new google.maps.LatLng(70.4043,-143.5291),  //Top-left
            new google.maps.LatLng(-46.11251, 163.4288)  //Bottom-right
        );
        mapObj.fitBounds(worldBounds, 0);
        var actualBounds = mapObj.getBounds();
        if(actualBounds.getSouthWest().lng() == -180 && actualBounds.getNorthEast().lng() == 180) {
            mapObj.setZoom(mapObj.getZoom()+1);
        }
    }
    
    0 讨论(0)
提交回复
热议问题