ios 旋转注解使用Swift查看特定坐标

nkhmeac6  于 2023-05-30  发布在  iOS
关注(0)|答案(2)|浏览(156)

我创建了苹果Map应用程序,并使用MKCircle和MKPolyline处理位置Map。
我用了

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? 
{}

在Map视图中更新自定义注记的上述方法。
事情是我可以旋转图像,而注解达到特定的时间点。
我要求将注解移动三个位置,从洛杉矶和纽约开始,最后是墨西哥城,因此当注解到达纽约时,我想旋转注解图像。请给我一些提示。
有关更多信息,请参阅下面的代码部分。

//
    //  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.
    }

}

谢谢。

x9ybnkn6

x9ybnkn61#

在我的例子中,我得到了到目的地的航向(Angular )。所以我在我的项目中这样做就像是对图像进行重新排列,而不是对注解视图进行重新排列。
//viewForAnnotation方法

annotationView.image = UIImage(named: "pointer")?.imageRotatedByDegrees(CGFloat(angle), flip: false)

我添加了一个扩展。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
   }
  }
inkz8wg9

inkz8wg92#

在这种情况下,我所做的是删除注解,并将其重新添加到具有更新图像的Map中。就像这样:

DispatchQueue.main.async {
        self.mkMapView.removeAnnotation(planeAnnotation)
        updatedAnnotation()
        self.mkMapview.addAnnotation(planeAnnotation)
    }

如果您有多个注解,并且只想更新其中的一部分,您可以循环所有注解,应用一些相关的过滤。例如:

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)
        }
    }

相关问题