Set MKMapView Span without moving map - swift

How do you adjust the MKMapView span (zoom) without moving the map location. I am trying to do this in an attempt to limit the user from zooming out further than preferable.

Use MKCoordinateSpanMake() method, for an instance
let span = MKCoordinateSpanMake(0.05, 0.05)

Try making the zoom with the MKMapView camera instead, adjusting eyeAltitude parameter can help you
func makeZoomWithCamera(){
let newCamera: MKMapCamera = MKMapCamera(lookingAtCenter: self.mapView.camera.centerCoordinate, fromEyeCoordinate: self.mapView.camera.centerCoordinate, eyeAltitude: 10)
self.mapView.setCamera(newCamera, animated: true)
}

Related

MGLSymbolStyleLayer "iconRotation" animation

is it possible to animate my marker rotation using MGLSymbolStyleLayer's iconRotation property ? or is there any other way to rotate my marker smoothly ?
I just want to rotate my marker smoothly , as of now the rotation is fine but it is quite snappy. Also i get different bearing for different markers from the server, is there any way i can rotate my marker using MGLPointAnnotation only ?. My use case is that i want different degree rotation for different markers (each of same icon)
let point = MGLPointAnnotation()
point.coordinate = CLLocationCoordinate2D(latitude: 30.699335, longitude: 76.836422)
let shapeSource = MGLShapeSource(identifier: "marker-source", shape: point, options: nil)
shapeLayer = MGLSymbolStyleLayer(identifier: "marker-style", source: shapeSource)
if let image = UIImage(named: "auto") {
mapView.style?.setImage(image, forName: "auto")
}
shapeLayer?.iconImageName = NSExpression(forConstantValue: "auto")
CATransaction.begin()
CATransaction.setAnimationDuration(3.0)
self.shapeLayer?.iconRotation = NSExpression(forConstantValue: 120.0)
CATransaction.commit()
You can animate an MGLSymbolStyleLayer using the add live data example. You would need to set your #objc function to layer.iconRotation and have that value change every time the function is executed. You can also do the same using an MGLPointFeature or MGLPointAnnotation as a source for an MGLSymbolStyleLayer. Please take a look at the Mapbox Add markers and shapes documentation here to see the different features that are supported.

How to Place Bottom Of a Custom Annotation On a Specific Coordinate in Mapbox iOS

I'm using iOS Mapbox SDK in my app. I changed image for an annotation to a custom image (It looks like a map marker). When I add an annotation to a specific coordinate on the map view, It will be added but the center of my custom annotation image (the marker) will be set on the coordinate. I need to change the marker position to set the bottom of the marker on the coordinate. I found a way but I do not know is there a better way or not?
I converted the coordinate to a point, then changed the point y position, then converted the point to a new coordinate.
func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? {
let reuseIdentifier = "annotationImage"
var annotationImage = mapView.dequeueReusableAnnotationImage(withIdentifier: reuseIdentifier)
if annotationImage == nil {
annotationImage = MGLAnnotationImage(image: UIImage(named: "Orange")!, reuseIdentifier: reuseIdentifier)
}
return annotationImage
}
func addDestinationMarker(coordinate: CLLocationCoordinate2D) {
guard let mapView = mapView else { return }
if let annotations = mapView.annotations {
mapView.removeAnnotations(annotations)
}
var point = mapView.convert(coordinate, toPointTo: mapView)
point.y -= markerImageView.frame.height / 2
let newCoordinate = mapView.convert(point, toCoordinateFrom: mapView)
let annotation = MGLPointAnnotation()
annotation.coordinate = newCoordinate
mapView.addAnnotation(annotation)
}
I've run into this same issue and started to think that round map pins were becoming the defacto standard so they could just be plonked onto the map with the image centre denoting the coordinate. However if you take a look at this example on the Mapbox website, they use a non-round image and solve the offset problem quite nicely.
// The anchor point of an annotation is currently always the center. To
// shift the anchor point to the bottom of the annotation, the image
// asset includes transparent bottom padding equal to the original image
// height.
//
// To make this padding non-interactive, we create another image object
// with a custom alignment rect that excludes the padding.
image = image.withAlignmentRectInsets(UIEdgeInsets(top: 0, left: 0, bottom: image.size.height/2, right: 0))
This does mean that you need to generate pin images that are twice as tall, with the lower half transparent, but that's really not a big deal.
You can solve this by leveraging the centerOffset property that MGLAnnotationView provides. Though I'm not sure if it's present in the MGLAnnotationImage you're using.
To set the anchor to the bottom of the annotation, use:
centerOffset.dy = -height / 2
If you set the frame beforehand, the height is simply frame.height.
The other answers express things correctly but both are missing the correct syntax:
annotationView?.centerOffset.y = -(annotationView?.frame.height ?? 0) / 2
This will achieve the expected result.

Swift4 - How to set the map's region to a location

this is my wrong code, it should give you an Idea of what I wanna achieve
let destCoordinates = CLLocationCoordinate2DMake(lat, long)
let annonation = MKPointAnnotation()
annonation.coordinate = destCoordinates
clientMap.addAnnotation(annonation)
self.clientMap.setRegion(MKCoordinateRegion(destCoordinates), animated: true)
You can't "just" set the the region to a coordinate. A map region consists not only of a coordinate (where the centre of the region is), but also a span (the width and height of that region). So saying something like "set the region of this map so that the centre is (0, 0)" makes no sense because you are missing the width and height of the region.
This means that you have to actively think about exactly how you want your region's span to be. In other words, how far zoomed in do you want your map to be?
If you want to remain at the same zoom level, for example, you could do this:
self.clientMap.setRegion(MKCoordinateRegion(center: destCoordindates, span: self.clientMap.region.span), animated: true)
But most of the time you probably want to zoom in to wherever your destCoordinates is for a good user experience. Try playing around with different values for the span, for example:
self.clientMap.setRegion(MKCoordinateRegion(center: destCoordindates, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)), animated: true)
You cannot simply cast coordinates to a region. A region takes coordinates as its center and a span as its dimensions. Read the documentation here.
This is the initializer:
MKCoordinateRegion(center: CLLocationCoordinate2D, span: MKCoordinateSpan)

Change Initial Zoom MapKit Swift

I'm new in Swift, and I'm trying to use MkMapView. I'd like to change the initial zoom. I searched On the API but I don't find anything.
I find only this, about zoom
mapView.zoomEnabled = true
But it isn't what I looking For.
MKMaps don't have a concept of zoom as a configurable variable. Zoom enabled pertains to user interaction. You'll need to configure something manually by setting a region that encompasses your desired zoom level.
For instance, if I wanted to zoom in on some specific coordinate, I could do:
let coordinate: CLLocationCoordinate2D = // .. populate your center
let latitudinalMeters: CLLocationDistance = 50
let longitudinalMeters: CLLocationDistance = 50
let region = MKCoordinateRegionMakeWithDistance(coordinate, latitudinalMeters, longitudinalMeters)
self.mapView.setRegion(region, animated: false) // Set to yes to animate, you said initial load so I image this won't be visible anyways.
Then, adjust the latitudinal/longitudinal dimensions to meet your desired zoom level.
If you wanted, you could probably create a category that adds zoom and calls this in the background.
From Logan's answer, update for Swift 5+
let coordinate: CLLocationCoordinate2D = // .. populate your center
let latitudinalMeters: CLLocationDistance = 50
let longitudinalMeters: CLLocationDistance = 50
let region = MKCoordinateRegion(center: coordinate, latitudinalMeters: latitudinalMeters, longitudinalMeters: longitudinalMeters)
self.mapView.setRegion(region, animated: false) // Set to yes to animate, you said initial load so I image this won't be visible anyways.

How to get coordinate center of gmsmapview in iphone

I'm using the new Google Maps SDK for iOS
Can I get the true coordinate form GMSMapView.center?
Now it returns a value of CGPoint, but it's not the true coordinate.
Thank and Regards.
Use the projection method - (CLLocationCoordinate2D)coordinateForPoint:(CGPoint)pointof the mapview to convert a point in the map to the geological coordinates
CGPoint point = mapView.center;
CLLocationCoordinate2D coor = [mapView.projection coordinateForPoint:point];
I suggest to use [yourMapView.camera target] instead of Jing's solution.
Jing's solution work fine on iOS 6, but maybe having issue on iOS 7/7.1,
the projection may report wrong coordinate (a bit downward shift) !
I have checked the map bounds and padding is correct, both result of [projection pointForCoordinate: coordinate] and [projection coordinateForPoint:point] can contrast to each other, no ideas where the problem is...
Here is how to do it in Swift 4
let coordinate = mapView.projection.coordinate(for: mapView.center)
Are you looking for mapView.camera.target? This is a CLLocationCoordinate2D.
Swift 4
let point = mapView.center
let coordinate = mapView.convert(point, toCoordinateFrom: mapView)
Perhaps a better way if the user is allowed to interact with the map is using the map's did-become-idle delegate method. Here you can get the center coordinate after each camera change.
func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
print(position.target)
}