User Current Location on specific position on MAP - ios

MKMapView
CoreLocation
Swift3.0
I have a requirement like this:
Creating an application in which I am getting Lat and Long for various location from webservice . Ploting these locations on map with Custom AnnotationView . Apart from this, I'm showing User Current Location with Custom Image.
Here everything working fine.
Now, when user moves then User Current Location Pin changes its position so there is an important requirement for this, I need to make this Current Location position in such a way that it stick in the bottom of map (just 100 pixel) above from bottom.
I did Some RND and find out few useful links:
Centering MKMapView on spot N-pixels below pin
How can I center my mapview so that the selected pin is not in the middle of the map but in 1/3 of it?
set current location icon lower side in MKMapView
But this not working anymore.
Kindly suggest how can I set user Current Location pin in iOS map in such a way that it always at the bottom of Map (100 pixel above from Bottom)
Required Pin position:
Currently it is showing in other position.
Note - **Dont want Google Map for such functionality.

If you have been using something like this mapView.setUserTrackingMode(.Follow, animated: true) then user location will be always displayed in the center of the map, zoom/pan will be automatically adjusted whenever user location is updated.
You need to disable the UserTrackingMode and then manually adjust the map zoom/pan using func setVisibleMapRect(_ mapRect: MKMapRect, edgePadding insets: UIEdgeInsets, animated animate: Bool) each time whenever user location is changed.
I used following code in similar situation
let annotationPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate);
var zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 1, 1);
annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 1, 1);
zoomRect = MKMapRectUnion(zoomRect, pointRect);
mapView.setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(40, 50, 160, 50), animated: true)
p.s. edgePadding is your friend in this case.

Here is the trick to use to position the map in such a way that UserLocation pin gets adjusted automatically :
func setUserLocationOnLowerPositiononMap(coordinate: CLLocationCoordinate2D) {
var region = MKCoordinateRegion(center: coordinate, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
region.center = coordinate
self.map.setRegion(region, animated: true)
//self.map.moveCenterByOffSet(offSet: CGPoint(x: 0, y: -130), coordinate: coordinate)
self.map.moveCenterByOffSet(offSet: CGPoint(x: 0, y: SCREEN_HEIGHT - SCREEN_HEIGHT * 4/3 + 0 ), coordinate: coordinate)
}

Related

How to view Apple Maps in a globe using Swift?

Looking for a solution I stumbled upon this post:
How to display entire globe in MKMapView
I followed the steps from Tushar Katyal but could not see a GLOBE. At least not in the simulator view. How should I apply this to be able to see a globe?
I already have a 2D view, and with a pin that resembles a range, and want to project it on a globe to be more accurate.
The code applied is this:
Function in viewDidLoad:
updateMapToShowGlobe(location: mapView.centerCoordinate)
declared function:
// MARK: Snippet to show full globe in 3d view
private func updateMapToShowGlobe(location :CLLocationCoordinate2D) {
let span = MKCoordinateSpanMake(130, 130)
let region = MKCoordinateRegionMake(location, span)
if( region.center.latitude > -90 && region.center.latitude < 90 && region.center.longitude > -180 && region.center.longitude < 180 ){
mapView.setRegion(region, animated: true)
}
}
I need to have a "world view" for some results, and a closer view zooming in but also on the globe, since I have to center pins in very northern locations.

HEREMaps iOS: Zoom to specific point

I need to zoom NMAMapView to specific point inside map bounds. Let's say we have some marker as subview of this map with position pinPoint: CGPoint.
I tried to use transformCenter property of NMAMapView like this:
let transformCenter = CGPoint(x: pinPoint.x / mapView.bounds.width, y: pinPoint.y / mapView.bounds.height) // x and y are in range [0, 1]
mapView.transformCenter = transformCenter
mapView.set(zoomLevel: mapView.zoomLevel + 1, animation: .linear)
But this code zooms map to its frame center, not to pinPoint.
I also tried to zoom map to needed point with code below:
guard let coordinates = mapView.geoCoordinates(from: pinPoint) else {
return
}
mapView.set(coordinates: coordinates, to: pinPoint, animation: .linear, zoomLevel: mapView.zoomLevel + 1)
But this also doesn't work correctly: after zooming, geo coordinates below marker were changed after each zoom step.
Please try to with this code, this code is just for your reference, You need to modify as per your requirements.
// create geo coordinate
let geoCoordCenter = NMAGeoCoordinates(latitude: 49.260327, longitude: -123.115025)
// set map view with geo center
self.mapView.set(geoCenter: geoCoordCenter, animation:NMAMapAnimation.none)
// set zoom level
self.mapView.zoomLevel = 13.2
Please check more example GitHub.

Swift mkmapview get zoom level, width or radius of visible map area from latitude longitude delta

I am in a confusion, on how to get a zoom level and radius of a visible area of the map (using mapkit mapview).
Here is what I am looking for (either of them or both, as needed) -
Zoom level, is to see at what level of the map is being shown to the users and with that information, I want to display the custom pins in the visible area. If zoom level is high, I need to show the actual logos of some commerce stores as pins. If zoom level is low, I need to show colored dots instead of logos.
As of now, I am using let updatedRadius = (mapView.camera.altitude)/1000 to get altitude of the camera, and if the updatedRadius value is > 25.0, I am showing colored dots. Below 25.0, I show the logos. I am doing this in regionDidChanged
Is this approach correct?
Radius, is to send it as a parameter to my REST API to fetch the list of places within that radius. When user zooms out on the map, visible area increases and so the REST API needs bigger radius to return the places covered in that area.
Ultimately, what should happen is, whenever user zooms out, then the radius changes. I need to send this changed radius to my REST to get an updated list.
What are latitude longtitude deltas, can we get radius/width of visible area using these values?
let latitudeDeltaVal = mapView.region.span.latitudeDelta
let longitudeDeltaVal = mapView.region.span.longitudeDelta
Can someone throw some light on what needs to be done please?
Since you need to call the api when the region changes you need to calculate the radius in mapView's delegate function, RegionDidChange.
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let centralLocation = CLLocation(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude)
self.centralLocationCoordinate = mapView.centerCoordinate
print("Radius - \(self.getRadius(centralLocation))")
}
func getRadius(centralLocation: CLLocation) -> Double{
let topCentralLat:Double = centralLocation.coordinate.latitude - mapView.region.span.latitudeDelta/2
let topCentralLocation = CLLocation(latitude: topCentralLat, longitude: centralLocation.coordinate.longitude)
let radius = centralLocation.distanceFromLocation(topCentralLocation)
return radius / 1000.0 // to convert radius to meters
}
To account for both landscape and portrait orientations, and/or situations where the map orientation is close to Northeast, Northwest, Southwest, Southeast, and to enclose the full screen up to the corners, one should consider both latitudeDelta and longitudeDelta:
func getRadius() -> Double{
let centralLocation = CLLocation(latitude: mapView.region.center.latitude, longitude: mapView.region.center.longitude)
let cornerOfMap = CLLocation(latitude: centralLocation.coordinate.latitude + mapView.region.span.latitudeDelta , longitude: centralLocation.coordinate.longitude + mapView.region.span.longitudeDelta)
let radius = centralLocation.distance(from: cornerOfMap)
return radius / 1000.0 // to convert radius to meters
}

Keep user location center in Google Maps - Swift

I have implemented Google maps in to a swift project and using locationManager to track and currently print out the users location.
I am also changing the camera position as the user moves around however this seems a bit jerky as the map moves then the blue dot (user location) moves.
Is there a way to keep the user location centered at all times and just have the map move?
you can easily enable
mapView.myLocationEnabled = true
and see this answer for more info to camera updating -> as it shows how to update camera with 2 positions or center a location
Plaese, see if this answer helps you. The user location is centered all the time in the example code. There is no camera adustment though, but that shouldn't make a difference.
Hope it helps.
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.map.setRegion(region, animated: true)

How to zoom in or out a MKMapView in Swift?

Objective
I need my app to zoom in or out a MKMapView.
Code
I thought of animating the value of the altitude of a MKMapCamera. Though, this doesn't zoom in or out the map.
let mapCamera = MKMapCamera()
mapCamera.altitude = 1000000
mapView.camera = mapCamera
UIView.animateWithDuration(10, delay: 0., options: UIViewAnimationOptions.CurveLinear, animations: {
mapCamera.altitude = 6000000
}, completion: {(finished: Bool) in
})
mapView.camera = mapCamera
Question
How do I zoom in or out a MKMapView? Are there any other ways to do so?
Here is an extension based on kevins answer https://stackoverflow.com/a/20129379/1488696
With it you'll be able to zoom in and out as required
extension MKMapView {
// delta is the zoom factor
// 2 will zoom out x2
// .5 will zoom in by x2
func setZoomByDelta(delta: Double, animated: Bool) {
var _region = region;
var _span = region.span;
_span.latitudeDelta *= delta;
_span.longitudeDelta *= delta;
_region.span = _span;
setRegion(_region, animated: animated)
}
}
Use it like so: myMapView.setZoomByDelta(0.5, animated: true)
MKMapCamera is used for 3D maps. So its likely not what you're looking for
Apple Docs
An MKMapCamera object describes a virtual camera that you use to define the appearance of the map. A camera object creates a virtual viewpoint above the map surface and affects how the map renders its tiles and other content. You use a camera object to specify the location of the camera on the map, the compass heading that corresponds to the camera’s viewing direction, the pitch of the camera relative to the map perpendicular, and the camera’s altitude above the map. These factors let you create a map view that is not just flat but offers a more 3D-like experience."
Use the method setRegion:animated:. It takes an MKCoordinateRegion parameter. The region includes a span, which determines the range of north-to-south latitude shown on the screen.

Resources