问题
I am working on an app that displays certain markers based on a radius around your current location. The radius is between 100 - 5000 meters. I change the radius with an UISlider
and redraw the GMSCircle
.
My problem is that I want to update the camera zoom according to the slider value but I don't have an idea by which scale to divide.
This is how I create the camera in the viewDidLoad
method where the initial zoom value is 15:
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:locationManager.location.coordinate.latitude longitude:locationManager.location.coordinate.longitude zoom:15];
Here's a screenshot of what I am working on.
Does anyone know what scale should I use to move the zoom accordingly?
Thanks a lot!
Granit
回答1:
With the help of Saxon Druce,finally I did it.
class MapUtil {
class func translateCoordinate(coordinate: CLLocationCoordinate2D, metersLat: Double,metersLong: Double) -> (CLLocationCoordinate2D) {
var tempCoord = coordinate
let tempRegion = MKCoordinateRegionMakeWithDistance(coordinate, metersLat, metersLong)
let tempSpan = tempRegion.span
tempCoord.latitude = coordinate.latitude + tempSpan.latitudeDelta
tempCoord.longitude = coordinate.longitude + tempSpan.longitudeDelta
return tempCoord
}
class func setRadius(radius: Double,withCity city: CLLocationCoordinate2D,InMapView mapView: GMSMapView) {
let range = MapUtil.translateCoordinate(city, metersLat: radius * 2, metersLong: radius * 2)
let bounds = GMSCoordinateBounds(coordinate: city, coordinate: range)
let update = GMSCameraUpdate.fitBounds(bounds, withPadding: 5.0) // padding set to 5.0
mapView.moveCamera(update)
// location
let marker = GMSMarker(position: city)
marker.title = "title"
marker.snippet = "snippet"
marker.flat = true
marker.map = mapView
// draw circle
let circle = GMSCircle(position: city, radius: radius)
circle.map = mapView
circle.fillColor = UIColor(red:0.09, green:0.6, blue:0.41, alpha:0.5)
mapView.animateToLocation(city) // animate to center
}
}
回答2:
Here's a simpler solution for getting the bounds of a GMSCircle
.
It doesn't rely on MapKit and avoids the two calls that change the camera position (moveCamera
and animateToLocation
)
import GoogleMaps
extension GMSCircle {
func bounds () -> GMSCoordinateBounds {
func locationMinMax(_ positive : Bool) -> CLLocationCoordinate2D {
let sign: Double = positive ? 1 : -1
let dx = sign * self.radius / 6378000 * (180 / .pi)
let lat = position.latitude + dx
let lon = position.longitude + dx / cos(position.latitude * .pi / 180)
return CLLocationCoordinate2D(latitude: lat, longitude: lon)
}
return GMSCoordinateBounds(coordinate: locationMinMax(true),
coordinate: locationMinMax(false))
}
}
After adding this file to your project, all you have to do is:
let update = GMSCameraUpdate.fit(myCircle.bounds())
myMap.animate(with: update)
where myCircle
and myMap
are replaced by the actual circle and map.
回答3:
You could use the fitBounds
method of GMSCameraUpdate, passing in a GMSCoordinateBounds
which is calculated from the edges of your circle.
Based on this answer, it looks like you could use MKCoordinateRegionMakeWithDistance
to convert your centre (lat/lon) plus radius (metres) into a MKCoordinateRegion
, which will convert the metres into a span in degrees, therefore allowing you to calculate the coordinates in degrees which you'd use to create the GMSCoordinateBounds
.
回答4:
I just created extension for GMSCameraUpdate.
input parameters:
coordinate - your center coordinate
radius - radius of visible bounds
extension GMSCameraUpdate {
static func fit(coordinate: CLLocationCoordinate2D, radius: Double) -> GMSCameraUpdate {
var leftCoordinate = coordinate
var rigthCoordinate = coordinate
let region = MKCoordinateRegionMakeWithDistance(coordinate, radius, radius)
let span = region.span
leftCoordinate.latitude = coordinate.latitude - span.latitudeDelta
leftCoordinate.longitude = coordinate.longitude - span.longitudeDelta
rigthCoordinate.latitude = coordinate.latitude + span.latitudeDelta
rigthCoordinate.longitude = coordinate.longitude + span.longitudeDelta
let bounds = GMSCoordinateBounds(coordinate: leftCoordinate, coordinate: rigthCoordinate)
let update = GMSCameraUpdate.fit(bounds, withPadding: -15.0)
return update
}
}
回答5:
For Swift 3
extension GMSCircle {
var bounds: GMSCoordinateBounds {
return [0, 90, 180, 270].map {
GMSGeometryOffset(position, radius, $0)
}.reduce(GMSCoordinateBounds()) {
$0.includingCoordinate($1)
}
}
}
Usage:
mapView.animate(with: .fit(circle.bounds))
来源:https://stackoverflow.com/questions/26115047/change-camera-zoom-based-on-radius-google-maps-ios-sdk