31

How to fit bounds for coordinate array with google maps sdk for iOS? I need to zoom map for 4 visible markers.

Mecid
  • 4,491
  • 6
  • 30
  • 30
  • I answered your similar question here: http://stackoverflow.com/questions/15040409/how-to-setregion-with-google-maps-sdk-for-ios – Saxon Druce Feb 28 '13 at 12:02

5 Answers5

73

Here's my solution for this problem. Building a GMSCoordinateBounds object by multiple coordinates.

- (void)focusMapToShowAllMarkers {       
    CLLocationCoordinate2D myLocation = ((GMSMarker *)_markers.firstObject).position;
    GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:myLocation coordinate:myLocation];

    for (GMSMarker *marker in _markers)
        bounds = [bounds includingCoordinate:marker.position];

    [_mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds withPadding:15.0f]];
}

Updated answer: Since GMSMapView markers property is deprecated, you should save all markers in your own array.

updated swift 3 answer:

    func focusMapToShowAllMarkers() {
        let firstLocation = (markers.first as GMSMarker).position
        var bounds = GMSCoordinateBoundsWithCoordinate(firstLocation, coordinate: firstLocation)
    
        for marker in markers {
            bounds = bounds.includingCoordinate(marker.position)
        }
        let update = GMSCameraUpdate.fitBounds(bounds, withPadding: CGFloat(15))
        self.mapView.animate(cameraUpdate: update)
  }
Lirik
  • 3,167
  • 1
  • 30
  • 31
  • 2
    Works fine. Although marker property has been deprecated now. I instead used marker locations I had in an array. – Manish Ahuja Dec 15 '13 at 08:30
  • Thank you, I used this great solution :) but as @ManishAhuja said, I used my own stored GMSMarker array to build the bounds. – Boda Aug 19 '14 at 19:07
  • Thanks @ManishAhuja and AubadaTaijo. Iv'e updated the answer. – Lirik Aug 20 '14 at 20:29
9

Swift 3.0 version of Lirik's answer:

func focusMapToShowAllMarkers() {
    let myLocation: CLLocationCoordinate2D = self.markers.first!.position
    var bounds: GMSCoordinateBounds = GMSCoordinateBounds(coordinate: myLocation, coordinate: myLocation)

    for marker in self.markers {
        bounds = bounds.includingCoordinate(marker.position)
        self.mapView.animate(with: GMSCameraUpdate.fit(bounds, withPadding: 15.0))
    }
}

And here's my own way:

func focusMapToShowMarkers(markers: [GMSMarker]) {

    guard let currentUserLocation = self.locationManager.location?.coordinate else {
        return
    }

    var bounds: GMSCoordinateBounds = GMSCoordinateBounds(coordinate: currentUserLocation,
                                                          coordinate: currentUserLocation)

    _ = markers.map {
        bounds = bounds.includingCoordinate($0.position)
        self.mapView.animate(with: GMSCameraUpdate.fit(bounds, withPadding: 15.0))
    }
}

And you can call my function above like so:

self.focusMapToShowMarkers(markers: [self.myLocationMarker, currentPokemonMarker])

Glenn Posadas
  • 12,555
  • 6
  • 54
  • 95
5

Swift 5 version of Lirik's answer:

    func focusMapToShowAllMarkers() {

        if arrMarkers.count > 0 {
            let firstLocation = (arrMarkers.first!).position
            var bounds = GMSCoordinateBounds(coordinate: firstLocation, coordinate: firstLocation)

            for marker in arrMarkers {
              bounds = bounds.includingCoordinate(marker.position)
            }

           let update = GMSCameraUpdate.fit(bounds, withPadding: CGFloat(15))
           self.mapView.animate(with: update)
        }
    }
MD.
  • 1,157
  • 11
  • 18
3

For time being, Google has finally implemented the GMSCoordinateBounds, you can make use of it with GMSCameraUpdate.

For details, please check the official reference.

Jagat Dave
  • 1,643
  • 3
  • 23
  • 30
Leslie
  • 37
  • 8
1

We can simplify this quite a bit, with code such as the following:

extension Array where Element: GMSMarker {
  func encompassingCoordinateBounds() -> GMSCoordinateBounds {
    reduce(GMSCoordinateBounds(), { $0.includingCoordinate($1.position) })
  }
}

The call site would like:

let markers = [GMSMarker]()
let encompassingCoordinateBounds = markers.encompassingCoordinateBounds()
D6mi
  • 611
  • 7
  • 16