在虚拟地图swift3上删除注释

时间:2017-03-14 10:02:38

标签: ios swift ibeacon

请帮帮我。

第一次参与项目,涉及iBeacon,在商店内部创建虚拟地图

我知道如何使用MapKit删除引脚,但是如果我在View上只有CGPoints,我怎么能这样做呢? 我设法如何在视图上滴下UIImage(带图像)。但是当我旋转或捏时,它不会停留在我丢弃的那个坐标上。 这是一个代码:

import UIKit



class MapViewController: UIViewController{


    private var scaleView: CGFloat = 1
    private var rotateView: CGFloat = 0
    private var anchorPoint = CGPoint(x: 0.5, y: 0.5)
    private let gestureRecognizerDelegate = GestureRecognizerDelegate()

    @IBOutlet weak var mapView: MapView!
    @IBOutlet var pinchGestureRecognizer: UIPinchGestureRecognizer!
    @IBOutlet var panGestureRecognizer: UIPanGestureRecognizer!
    @IBOutlet var rotateGestureRecognizer: UIRotationGestureRecognizer!
    @IBOutlet weak var pin: UIImageView!

    override func viewDidAppear(_ animated: Bool) {
        if !cartIsEmpty {
            cartBtn.setImage(UIImage(named: "haveitem"), for: .normal)

        } else {
            cartBtn.setImage(UIImage(named: "2772"), for: .normal)

        }
        cartBtn.addTarget(self, action: #selector(openCart), for: .touchUpInside)
        let item1 = UIBarButtonItem(customView: cartBtn)
        self.navigationItem.rightBarButtonItem = item1
    }
    override func viewDidDisappear(_ animated: Bool) {
        cartBtn.removeTarget(self, action: #selector(openCart), for: .touchUpInside)

    }

    override func viewDidLoad() {
        super.viewDidLoad()
            ApplicationManager.sharedInstance.onApplicationStart()
        NotificationCenter.default.addObserver(self, selector: #selector(self.onOrientationChanged), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
        self.panGestureRecognizer.delegate = gestureRecognizerDelegate
        self.pinchGestureRecognizer.delegate = gestureRecognizerDelegate
        self.rotateGestureRecognizer.delegate = gestureRecognizerDelegate
        ApplicationManager.sharedInstance.gotFloorData = drawFloor
        ApplicationManager.sharedInstance.currentUserPoint = drawCurrentUserPoint
    }

    func drawFloor (floor: Floor) {
        mapView.setFloor(currentFloor: floor)
        mapView.setNeedsDisplay()
    }

    func drawCurrentUserPoint(currentUserPoint: CurrentUserLocation, beaconRangingData: [BeaconRangingPoint]) {
        mapView.setUserPoint(currentUserPoint: currentUserPoint, beaconRangingData: beaconRangingData)
        mapView.setNeedsDisplay()
    }

    @IBAction func handlePan(recognizer:UIPanGestureRecognizer) {
        let translation = recognizer.translation(in: mapView)
        if recognizer.view != nil {
            let offsetX = translation.x * CGFloat(cosf(Float(rotateView))) - translation.y * CGFloat(sinf(Float(rotateView)))
            let offsetY = translation.x * CGFloat(sinf(Float(rotateView))) + translation.y * CGFloat(cosf(Float(rotateView)))
            mapView.center = CGPoint(x:mapView.center.x + offsetX * scaleView,
                                     y:mapView.center.y + offsetY * scaleView)
        }
        recognizer.setTranslation(CGPoint(x: 0, y: 0), in: mapView)
    }

    @IBAction func handlePinch(recognizer : UIPinchGestureRecognizer) {
        if recognizer.view != nil {
            setAnchor(point: recognizer.location(in: mapView))
            mapView.transform = mapView.transform.scaledBy(x: recognizer.scale, y: recognizer.scale)
            scaleView = recognizer.scale * scaleView
            recognizer.scale = 1
        }
    }

    @IBAction func handleRotate(recognizer : UIRotationGestureRecognizer) {
        if recognizer.view != nil {
            setAnchor(point: recognizer.location(in: mapView))
            mapView.transform = mapView.transform.rotated(by: recognizer.rotation)
            rotateView = rotateView + recognizer.rotation
            recognizer.rotation = 0
        }
    }

    private func setAnchor(point : CGPoint) {
        let anchor = CGPoint(x: point.x / mapView.bounds.width, y: point.y / mapView.bounds.height)
        mapView.layer.anchorPoint = CGPoint(x: anchor.x, y: anchor.y)
        let translationX = (mapView.bounds.width * (anchor.x - anchorPoint.x)) * scaleView
        let translationY = (mapView.bounds.height * (anchor.y - anchorPoint.y)) * scaleView
        let offsetX = translationX * CGFloat(cosf(Float(rotateView))) - translationY * CGFloat(sinf(Float(rotateView)))
        let offsetY = translationX * CGFloat(sinf(Float(rotateView))) + translationY * CGFloat(cosf(Float(rotateView)))
        mapView.layer.position = CGPoint(x: mapView.layer.position.x + offsetX,
                                         y: mapView.layer.position.y + offsetY)
        anchorPoint = anchor
    }

    private func showAlert(title: String, message: String?, style: UIAlertControllerStyle = .alert) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: style)
        let tryAgainAction = UIAlertAction(title: "Try again", style: .default) {
            alertAction in
            ApplicationManager.sharedInstance.onApplicationStart()
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
        alertController.addAction(tryAgainAction)
        alertController.addAction(cancelAction)
        present(alertController, animated: true, completion: nil)
    }

    func onOrientationChanged() {
        self.mapView.setNeedsDisplay()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

也是mapView的代码:

import UIKit

类MapView:UIView {

private var floor = Floor(walls: [], doors: [], beacons: [])
private let wallColor = UIColor.black
private let doorColor = UIColor.red
private let triangleColor = UIColor.red
private let perpendicularColor = UIColor.darkGray
private let doorLength = 3.0
private let beaconColor = UIColor.green
private let beaconNoActiveColor = UIColor(red: 20/255.0, green: 154.0/255.0, blue: 53.0/255.0, alpha: 1.0)
private let beaconFrameColor = UIColor.brown
private let lineWidthBeaconFrame:CGFloat = 0.25
private let beaconRadius: CGFloat = 5.0
private let userColor = UIColor.blue
private let userFrameColor = UIColor.brown
private let lineWidthUserFrame:CGFloat = 0.25
private let userRadius: CGFloat = 5.0
private let distanceBeaconColor = UIColor.clear
private let distanceBeaconFrameColor = UIColor.green
private let lineWidthOfDistanceFrame: CGFloat = 0.5
private let userRawRadius: CGFloat = 3.0
private let userRawColor = UIColor.darkGray
private let userRawFrameColor = UIColor.lightGray
private let lineWidthOfuserRawFrame: CGFloat = 0.8

private var beaconText: NSString = ""
private let textColor: UIColor = UIColor.red
private let textFont: UIFont = UIFont(name: "Helvetica Neue", size: 5)!


private var currentUserLocation = CurrentUserLocation()
private var beaconRangingData: [BeaconRangingPoint] = []

func setFloor (currentFloor: Floor) {
    floor = currentFloor
}
func setUserPoint(currentUserPoint: CurrentUserLocation, beaconRangingData: [BeaconRangingPoint]) {
    self.currentUserLocation = currentUserPoint
    self.beaconRangingData = beaconRangingData
}
func dropPin(location: CGPoint) {
}

override func draw(_ rect: CGRect) {
    let frameToDraw = CoordinatesConverter(boundsWidth: bounds.width, boundsHeight: bounds.height, paddingX: 5, paddingY: 5)
    let mapWithScaleCoordinaates =  frameToDraw.getSuitableCoordinates(floor: floor, currentUserLocation: currentUserLocation, beaconRangingData: beaconRangingData)
    let lines = mapWithScaleCoordinaates.lines
    let circles = mapWithScaleCoordinaates.circles

    drawLines(lines: lines)
    drawCircles(circles: circles)
 }

private func drawLines(lines :[Line]) {
    let wallPath = UIBezierPath()
    let doorPath = UIBezierPath()
    let trianglePath = UIBezierPath()
    let perpendicularPath = UIBezierPath()

    for line in lines {
        if line.type == .wall {
            wallPath.move(to: CGPoint(x: line.x1, y: line.y1))
            wallPath.addLine(to: CGPoint(x: line.x2, y: line.y2))
            wallColor.setStroke()
            wallPath.stroke()
        }
        if line.type == .door {
            doorPath.move(to: CGPoint(x: line.x1, y: line.y1))
            doorPath.addLine(to: CGPoint(x: line.x2, y: line.y2))
            doorPath.lineWidth = CGFloat(doorLength)
            doorColor.setStroke()
            doorPath.stroke()
        }
        if line.type == .triangle {
            trianglePath.move(to: CGPoint(x: line.x1, y: line.y1))
            trianglePath.addLine(to: CGPoint(x: line.x2, y: line.y2))
            triangleColor.setStroke()
            trianglePath.stroke()
        }
        if line.type == .perpendicular {
            perpendicularPath.move(to: CGPoint(x: line.x1, y: line.y1))
            perpendicularPath.addLine(to: CGPoint(x: line.x2, y: line.y2))
            perpendicularColor.setStroke()
            perpendicularPath.stroke()
        }
    }
}

private func drawCircles(circles: [Circle]) {
    let layerViews = layer.sublayers
    if layerViews != nil {
        for view in layerViews! {
            if type(of: view) === CAShapeLayer.self {
                view.removeFromSuperlayer()
            }
        }
    }

    for circle in circles {

        if type(of: circle) === BeaconCircle.self  {
            if (circle as! BeaconCircle).correctedDistance  == 0 {
                infoToDrawCircle(circle: circle, radius: beaconRadius, color: beaconNoActiveColor.cgColor, frameColor: beaconFrameColor.cgColor, frameWidth: lineWidthBeaconFrame)
                drawBeaconText(circle: circle as! BeaconCircle)
            } else {
                infoToDrawCircle(circle: circle, radius: beaconRadius, color: beaconColor.cgColor, frameColor: beaconFrameColor.cgColor, frameWidth: lineWidthBeaconFrame)
                drawBeaconText(circle: circle as! BeaconCircle)
            }

            if type(of: circle) === BeaconCircle.self && (circle as! BeaconCircle).correctedDistance != 0 {
                infoToDrawCircle(circle: circle, radius: CGFloat((circle as! BeaconCircle).correctedDistance), color: distanceBeaconColor.cgColor, frameColor: distanceBeaconFrameColor.cgColor, frameWidth: lineWidthOfDistanceFrame)
              //   infoToDrawCircle(circle: circle, radius: CGFloat((circle as! BeaconCircle).notCorrectedDistance), color: UIColor.gray.cgColor, frameColor: distanceBeaconFrameColor.cgColor, frameWidth: lineWidthOfDistanceFrame)
            }

        } else if type(of: circle) === UserCircle.self {
            infoToDrawCircle(circle: circle, radius: userRadius, color: userColor.cgColor, frameColor: userFrameColor.cgColor, frameWidth: lineWidthUserFrame)
        } else if type (of: circle) === UserRawCircle.self {
            infoToDrawCircle(circle: circle, radius: userRawRadius, color: userRawColor.cgColor, frameColor: userRawFrameColor.cgColor, frameWidth: lineWidthOfuserRawFrame)
        } else {
            Logger.logMessage(message: "incorrect circle type", level: .error)
            break
        }
    }
}



private func drawBeaconText (circle: BeaconCircle) {
    let attributes: NSDictionary = [
        NSForegroundColorAttributeName: textColor,
        NSFontAttributeName: textFont
    ]
    let minor = circle.minor
    let correctDistance = Int(round(100 * circle.correctDistanceForText) / 100)
    let notCorrectDistance = Int(round(100 * circle.notCorrectDistanceForText) / 100)
    beaconText = "m: \(minor), cd: \(correctDistance), nd: \(notCorrectDistance)" as NSString
    if circle.x > Int((bounds.width - 50)) {
        beaconText.draw(at: CGPoint(x: circle.x - 70, y: circle.y + 5), withAttributes: attributes as? [String : Any])
    } else if circle.x < 20 {
        beaconText.draw(at: CGPoint(x: circle.x + 5, y: circle.y + 5), withAttributes: attributes as? [String : Any])
    } else {
         beaconText.draw(at: CGPoint(x: circle.x + 6, y: circle.y + 5), withAttributes: attributes as? [String : Any])
    }
}

private func infoToDrawCircle (circle: Circle, radius: CGFloat, color: CGColor, frameColor: CGColor, frameWidth: CGFloat) {
    let center = CGPoint(x: circle.x, y: circle.y)
    let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: 360, clockwise: true)
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = path.cgPath
    shapeLayer.fillColor = color
    shapeLayer.lineWidth = frameWidth
    shapeLayer.strokeColor = frameColor
    layer.addSublayer(shapeLayer)
}

}

1 个答案:

答案 0 :(得分:0)

我建议您将MapViewControllerMKMapViewDelegate相符。通过这种方式,您可以向地图添加注释(也是动画),您不必再担心它们,因为它们都由地图委托处理。

您可以使用:

self.map.showAnnotations(pins, animated: true)

其中pinsMKAnnotation的数组。 Here is the link到方法的文档。

干杯