Reputation: 443
I created the apple map application and handled location mapping using MKCircle and MKPolyline.
And I used
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
{}
above method for Custom annotation update in the map view.
Thing is can i rotate the image while the annotation reaching particular point of time.
My requirement moving the annotation by three locations started from Los angeles and New York finally Mexico City, So while the annotation reaching New York I want to rotate the annotation image. Is it possible please suggest me some note.
For more info please find the below coding part.
//
// ViewController.swift
// RouteMap
//
// Created by Suthan M.
// Copyright © 2016 suthan.nimalan.m All rights reserved.
//
import UIKit
import MapKit
extension Double {
/** Converts the specified value in degrees into radians. */
func degrees() -> CGFloat {
return CGFloat(self) * CGFloat(M_PI / 180.0)
}
}
class ViewController: UIViewController,MKMapViewDelegate {
@IBOutlet var mkMapView: MKMapView!
var flightpathPolyline: MKGeodesicPolyline!
var planeAnnotation: MKPointAnnotation!
var planeAnnotationPosition = 0
var planeDirection: CLLocationDirection!
var testValue: MKMapPoint!
var testCount: Int!
var radiusInSomething : CLLocationDistance = 10000000.0
var circle:MKCircle!
override func viewDidAppear(animated: Bool) {
let location = CLLocationCoordinate2D(
latitude: 33.9424955,
longitude: -118.4080684
)
self.mkMapView.setRegion(MKCoordinateRegion(center: location, span: MKCoordinateSpan(latitudeDelta: 95, longitudeDelta: 95)), animated: true)
let LAX = CLLocation(latitude: 33.9424955, longitude: -118.4080684)
let JFK = CLLocation(latitude: 40.6397511, longitude: -73.7789256)
let WAS = CLLocation(latitude: 19.432608, longitude: -99.133209)
let mexicoCityLoc = CLLocationCoordinate2D(latitude: 19.4284700, longitude: -99.1276600)
mkMapView.addOverlay(MKCircle(centerCoordinate: mexicoCityLoc,
radius: radiusInSomething * MKMetersPerMapPointAtLatitude(mexicoCityLoc.latitude)))
var coordinates = [LAX.coordinate, JFK.coordinate, WAS.coordinate]
flightpathPolyline = MKGeodesicPolyline(coordinates: &coordinates, count: 3)
mkMapView.addOverlay(flightpathPolyline)
let coordin = CLLocationCoordinate2D(latitude: 19.4284700, longitude: -99.1276600)
circle = MKCircle(centerCoordinate: coordin, radius: 2000)
mkMapView.addOverlay(circle)
let annotation = MKPointAnnotation()
annotation.title = NSLocalizedString("Plane", comment: "Plane marker")
mkMapView.addAnnotation(annotation)
self.planeAnnotation = annotation
self.updatePlanePosition()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Work with MKMapview
self.planeDirection = 360.0
testCount = 0
mkMapView.delegate = self
mkMapView.mapType = MKMapType.Standard
mkMapView.showsUserLocation = true
}
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.lineWidth = 3.0
renderer.alpha = 0.5
renderer.strokeColor = UIColor.blueColor()
return renderer
}else if overlay is MKCircle {
let circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.fillColor = UIColor.blueColor().colorWithAlphaComponent(0.1)
circleRenderer.strokeColor = UIColor.blueColor()
circleRenderer.lineWidth = 1
return circleRenderer
}
return MKOverlayRenderer()
}
func updatePlanePosition() {
let step = 5
guard planeAnnotationPosition + step < flightpathPolyline.pointCount
else { return }
let points = flightpathPolyline.points()
self.planeAnnotationPosition += step
let nextMapPoint = points[planeAnnotationPosition]
self.planeAnnotation.coordinate = MKCoordinateForMapPoint(nextMapPoint)
let previousMapPoint = points[planeAnnotationPosition]
planeAnnotationPosition += step
self.planeDirection = directionBetweenPoints(previousMapPoint, nextMapPoint)
// set turn point of plane
if(testValue.x == 79197107.0566392){
testCount = 1
planeDirection = 360.0
self .mapView(mkMapView, viewForAnnotation: planeAnnotation )
}
performSelector("updatePlanePosition", withObject: nil, afterDelay: 0.03)
}
private func directionBetweenPoints(sourcePoint: MKMapPoint, _ destinationPoint: MKMapPoint) -> CLLocationDirection {
//print(sourcePoint)
//MKMapPoint(x: 74074213.8054451, y: 105154930.159039)
//MKMapPoint(x: 74074213.8054451, y: 105154930.159039)
testValue = sourcePoint
let x = destinationPoint.x - sourcePoint.x
let y = destinationPoint.y - sourcePoint.y
return radiansToDegrees(atan2(y, x)) % 360 + 90
}
private func radiansToDegrees(radians: Double) -> Double {
return radians * 180 / M_PI
}
private func degreesToRadians(degrees: Double) -> Double {
return degrees * M_PI / 180
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let planeIdentifier = "Plane"
let annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(planeIdentifier)
?? MKAnnotationView(annotation: annotation, reuseIdentifier: planeIdentifier)
annotationView.image = UIImage(named: "pointer")
if(testCount == 1){
let angle = CGFloat(self.degreesToRadians(self.planeDirection))
annotationView.transform = CGAffineTransformRotate(mapView.transform, angle)
}
else{
let angle = CGFloat(degreesToRadians(planeDirection))
annotationView.transform = CGAffineTransformRotate(mapView.transform, angle)
}
return annotationView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Thanks.
Upvotes: 3
Views: 1822
Reputation: 537
What I do in this case is delete the annotation and re-add it to the map with the updated image. Something like that:
DispatchQueue.main.async {
self.mkMapView.removeAnnotation(planeAnnotation)
updatedAnnotation()
self.mkMapview.addAnnotation(planeAnnotation)
}
If you have several annotations and want to update only some of them, you can loop on all annotations, applying some relevant filtering. Eg:
DispatchQueue.main.async {
for annotation in self.mkMapView.annotations.filter({ [insert the relevant filter here, eg $0 is PlaneAnnotation] }) {
self.mkMapView.removeAnnotation(annotation)
updatedAnnotation(annotation) // or any other routine updating the annotation image
self.mkMapview.addAnnotation(annotation)
}
}
Upvotes: 0
Reputation: 849
In my case i got the heading (angle) to the destination . So i did it in my project is like rorate the image not the annotation view.
//viewForAnnotation method
annotationView.image = UIImage(named: "pointer")?.imageRotatedByDegrees(CGFloat(angle), flip: false)
I added a extension .https://ruigomes.me/blog/how-to-rotate-an-uiimage-using-swift/
extension UIImage {
public func imageRotatedByDegrees(degrees: CGFloat, flip: Bool) -> UIImage {
// let radiansToDegrees: (CGFloat) -> CGFloat = {
// return $0 * (180.0 / CGFloat(M_PI))
// }
let degreesToRadians: (CGFloat) -> CGFloat = {
return $0 / 180.0 * CGFloat(M_PI)
}
// calculate the size of the rotated view's containing box for our drawing space
let rotatedViewBox = UIView(frame: CGRect(origin: CGPointZero, size: size))
let t = CGAffineTransformMakeRotation(degreesToRadians(degrees));
rotatedViewBox.transform = t
let rotatedSize = rotatedViewBox.frame.size
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize)
let bitmap = UIGraphicsGetCurrentContext()
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width / 2.0, rotatedSize.height / 2.0);
// // Rotate the image context
CGContextRotateCTM(bitmap, degreesToRadians(degrees));
// Now, draw the rotated/scaled image into the context
var yFlip: CGFloat
if (flip) {
yFlip = CGFloat(-1.0)
} else {
yFlip = CGFloat(1.0)
}
CGContextScaleCTM(bitmap, yFlip, -1.0)
CGContextDrawImage(bitmap, CGRectMake(-size.width / 2, -size.height / 2, size.width, size.height), CGImage)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}
Upvotes: 1