How to detect taps on MKPolylines/Overlays like Maps.app?

后端 未结 8 878
梦谈多话
梦谈多话 2020-12-23 02:09

When displaying directions on the built-in Maps.app on the iPhone you can \"select\" one of the usually 3 route alternatives that are displayed by tapping on it. I wan\'t to

8条回答
  •  借酒劲吻你
    2020-12-23 02:45

    The solution proposed below by Jensemann is working great. See below code adapted for Swift 2, tested successfully on IOS 8 and 9 (XCode 7.1).

    func didTapMap(gestureRecognizer: UIGestureRecognizer) {
        tapPoint = gestureRecognizer.locationInView(mapView)
        NSLog("tapPoint = %f,%f",tapPoint.x, tapPoint.y)
        //convert screen CGPoint tapPoint to CLLocationCoordinate2D...
        let tapCoordinate = mapView.convertPoint(tapPoint, toCoordinateFromView: mapView)
        let tapMapPoint = MKMapPointForCoordinate(tapCoordinate)
        print("tap coordinates = \(tapCoordinate)")
        print("tap map point = \(tapMapPoint)")
    
        // Now we test to see if one of the overlay MKPolyline paths were tapped
        var nearestDistance = Double(MAXFLOAT)
        let minDistance = 2000      // in meters, adjust as needed
        var nearestPoly = MKPolyline()
        // arrayPolyline below is an array of MKPolyline overlaid on the mapView
        for poly in arrayPolyline {                
            // ... get the distance ...
            let distance = distanceOfPoint(tapMapPoint, poly: poly)
            print("distance = \(distance)")
            // ... and find the nearest one
            if (distance < nearestDistance) {
                nearestDistance = distance
                nearestPoly = poly
            }
        }
        if (nearestDistance <= minDistance) {
            NSLog("Touched poly: %@\n    distance: %f", nearestPoly, nearestDistance);
        }
    }
    
    
    func distanceOfPoint(pt: MKMapPoint, poly: MKPolyline) -> Double {
        var distance: Double = Double(MAXFLOAT)
        var linePoints: [MKMapPoint] = []
        var polyPoints = UnsafeMutablePointer.alloc(poly.pointCount)
        for point in UnsafeBufferPointer(start: poly.points(), count: poly.pointCount) {
            linePoints.append(point)
            print("point: \(point.x),\(point.y)")
        }
        for n in 0...linePoints.count - 2 {
            let ptA = linePoints[n]
            let ptB = linePoints[n+1]
            let xDelta = ptB.x - ptA.x
            let yDelta = ptB.y - ptA.y
            if (xDelta == 0.0 && yDelta == 0.0) {
                // Points must not be equal
                continue
            }
            let u: Double = ((pt.x - ptA.x) * xDelta + (pt.y - ptA.y) * yDelta) / (xDelta * xDelta + yDelta * yDelta)
            var ptClosest = MKMapPoint()
            if (u < 0.0) {
                ptClosest = ptA
            } else if (u > 1.0) {
                ptClosest = ptB
            } else {
                ptClosest = MKMapPointMake(ptA.x + u * xDelta, ptA.y + u * yDelta);
            }
            distance = min(distance, MKMetersBetweenMapPoints(ptClosest, pt))
        }
        return distance
    }
    

提交回复
热议问题