move animation with custom annotation IOS Swift Like Ola Uber App MapKit

六眼飞鱼酱① 提交于 2019-11-29 02:42:33

As far as I understood your question I am proposing this solution in which i have drawn a polly live between two locations, Once user tap on that car annotation car annotation will run on path same like uber.

You can animate your custom annotation by making custom method  moveCar(_ destinationCoordinate : CLLocationCoordinate2D) and  passing latest value of coordinate which you are getting from server.

ViewController

    import UIKit
    import MapKit

    class ViewController: UIViewController {

        //--------------------------------------------------
        //MARK
        //MARK: - IBOutlets
        //--------------------------------------------------

        @IBOutlet weak var mapView: MKMapView!

        var pointAnnotation   : CarCustomAnnotation!
        var pinAnnotationView : MKAnnotationView!
        let sourceCoordinate  : CLLocationCoordinate2D? = CLLocationCoordinate2D(latitude: 23.034373 , longitude: 72.564163)
        let destinationCoordinate : CLLocationCoordinate2D? =  CLLocationCoordinate2D(latitude: 23.035141,longitude:72.564451)

        let reuseIdentifier = "pin"

        //--------------------------------------------------
        //MARK:
        //MARK: - Custom Methods
        //--------------------------------------------------

        func degreesToRadians(degrees: Double) -> Double { return degrees * .pi / 180.0 }

        func radiansToDegrees(radians: Double) -> Double { return radians * 180.0 / .pi }

        func getHeadingForDirectionFromCoordinate (_ fromLoc : CLLocationCoordinate2D , toLoc : CLLocationCoordinate2D) -> Double {

            let  fLat = degreesToRadians(degrees: fromLoc.latitude)
            let  fLng = degreesToRadians(degrees: fromLoc.longitude)
            let  tLat = degreesToRadians(degrees: toLoc.latitude)
            let  tLng = degreesToRadians(degrees: toLoc.latitude)

            let degree = radiansToDegrees(radians: atan2(sin(tLng-fLng) * cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)))

            if (degree >= 0) {
                return degree
            } else {
                return 360.0 + degree
            }
        }

        //--------------------------------------------------
        //MARK:
        //MARK: - View Life Cycle Methods
        //--------------------------------------------------

        override func viewDidLoad() {
            super.viewDidLoad()
            //Configure Custom Annotation and Add to CustomAnnotation View
            pointAnnotation = CarCustomAnnotation()
            pointAnnotation.pinCustomImageName = "car"
            pointAnnotation.coordinate = sourceCoordinate!
            pinAnnotationView = MKAnnotationView(annotation: pointAnnotation, reuseIdentifier: reuseIdentifier)

            //Set MapView for Showing Car Pin Annotation to One Region
            mapView.delegate = self
            mapView.addAnnotation(pinAnnotationView.annotation!)
            mapView.setCenter(sourceCoordinate!, animated: true)
            mapView.setRegion(MKCoordinateRegionMakeWithDistance(sourceCoordinate!, 140, 140), animated: true)
        }

    }

    extension ViewController : MKMapViewDelegate {

        func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            if overlay is MKPolyline {
                let polylineRenderer = MKPolylineRenderer(overlay: overlay)
                polylineRenderer.strokeColor = UIColor.blue
                polylineRenderer.lineWidth = 4.0
                return polylineRenderer
            }
            return MKOverlayRenderer()
        }

        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
            if annotationView == nil {
                annotationView = MKAnnotationView(annotation: annotationView?.annotation, reuseIdentifier: reuseIdentifier)
                annotationView?.canShowCallout = false
            } else {
                annotationView?.annotation = annotation
                annotationView?.canShowCallout = false
            }
            annotationView?.image = UIImage.init(named:pointAnnotation.pinCustomImageName)
            return annotationView
        }

        func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
            //Set PolyLine Between Source and Destinattion
            let polyline = MKPolyline(coordinates: [sourceCoordinate!,destinationCoordinate!], count: 2)
            mapView.add(polyline)
            pointAnnotation.courseDegrees =  self.getHeadingForDirectionFromCoordinate(sourceCoordinate!, toLoc: destinationCoordinate!)
             view.transform = CGAffineTransform(rotationAngle:CGFloat(pointAnnotation.courseDegrees))
             self.moveCar(self.destinationCoordinate!)
        }
        //Inert Animation Duration and Destination Coordinate which you are getting from server.
        func  moveCar(_ destinationCoordinate : CLLocationCoordinate2D) {
            UIView.animate(withDuration: 20, animations: {
                self.pointAnnotation.coordinate = destinationCoordinate
            }, completion:  { success in
                if success {
                    // handle a successfully ended animation
                    self.resetCarPosition()
                } else {
                    // handle a canceled animation, i.e move to destination immediately
                    self.pointAnnotation.coordinate = destinationCoordinate
                }
            })
        }

        func resetCarPosition() {
            self.pointAnnotation.courseDegrees = 0.0
            self.mapView.remove(self.mapView.overlays[0])
            self.pinAnnotationView.transform = CGAffineTransform(rotationAngle:CGFloat(pointAnnotation.courseDegrees))
            self.pointAnnotation.coordinate = self.sourceCoordinate!
        }
    }

CarCustomAnnotation

    import UIKit
    import MapKit

    class CarCustomAnnotation: MKPointAnnotation {
        var pinCustomImageName:String!
        var courseDegrees : Double! // Change The Value for Rotating Car Image Position
    }

MarkerAnnotationView

    import UIKit
    import MapKit

    class MarkerAnnotationView: MKAnnotationView {
        override var annotation: MKAnnotation? {
            willSet {
                guard let annotation = newValue as? CarCustomAnnotation else { return }
                image = UIImage.init(named: annotation.pinCustomImageName)
            }
        }
    }

Also find working full demo using this link:https://www.dropbox.com/s/8x42mm9vmtoeovd/AnnotationMovingDemo.zip?dl=0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!