检测地图圆圈叠加中的点击总是返回 false

Mon*_*key 2 mapkit ios swift

我有一个带有圆形叠加层的地图,它总是从 CGPathContainsPoint 方法返回 false。我是否传入了错误的 tapPoint 值?

func didTapMap(gestureRecognizer: UIGestureRecognizer) {
    let tapPoint: CGPoint = gestureRecognizer.locationInView(map)
    NSLog("%@,%@",tapPoint.x, tapPoint.y)

    for overlay in self.map.overlays{
        if (overlay.isKindOfClass(MKCircle))
        {
            let circle = overlay as MKCircle
            let circleRenderer:MKCircleRenderer = map.rendererForOverlay(circle) as MKCircleRenderer
            circleRenderer.invalidatePath()
            let mapCoordinateIsInCircle = CGPathContainsPoint(circleRenderer.path, nil, tapPoint, false)

            if (mapCoordinateIsInCircle == true)
            {
                NSLog("tapped in circle");
                break
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

小智 6

是的,错误的抽头点值被传递给CGPathContainsPoint

叠加渲染器中的值path不在屏幕CGPoint单位中。
path包含的值对应于渲染自己的绘画语境是从屏幕上不同。

您需要首先将作为屏幕的抽头点转换CGPoint为渲染器绘图上下文中的一个点。

MKOverlayRenderer( 的基类MKCircleRenderer) 具有pointForMapPoint:可以提供帮助的方法,但它需要一个MKMapPoint(不是 screen CGPoint)。

因此,您需要将屏幕转换CGPoint为一个MKMapPoint,然后最终转换为渲染器上下文中的一个点。

要从 screen 转换CGPointMKMapPoint,您需要首先CLLocationCoordinate2D使用地图视图将其转换为 a convertPoint:toCoordinateFromView:,然后MKMapPoint使用该MKMapPointForCoordinate函数将其转换为 a 。

例子:

func didTapMap(gestureRecognizer: UIGestureRecognizer) {
    let tapPoint: CGPoint = gestureRecognizer.locationInView(map)
    NSLog("tapPoint = %f,%f",tapPoint.x, tapPoint.y)

    //convert screen CGPoint tapPoint to CLLocationCoordinate2D...
    let tapCoordinate = map.convertPoint(tapPoint, toCoordinateFromView: map)

    //convert CLLocationCoordinate2D tapCoordinate to MKMapPoint...
    let tapMapPoint = MKMapPointForCoordinate(tapCoordinate)

    for overlay in self.map.overlays{
        if (overlay.isKindOfClass(MKCircle))
        {
            let circle = overlay as MKCircle
            let circleRenderer:MKCircleRenderer = map.rendererForOverlay(circle) as MKCircleRenderer

            //convert MKMapPoint tapMapPoint to point in renderer's context...
            let tapRendererPoint = circleRenderer.pointForMapPoint(tapMapPoint)

            circleRenderer.invalidatePath()

            let mapCoordinateIsInCircle = CGPathContainsPoint(circleRenderer.path, nil, tapRendererPoint, false)

            if (mapCoordinateIsInCircle == true)
            {
                NSLog("tapped in circle");
                break
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


顺便说一下,对于圆,检测其中的抽头的更简单方法是计算抽头点与圆心的距离。如果敲击点距离小于或等于圆的半径,则它是圆内的敲击。

这样,您就不需要获取圆的渲染器、其路径或 CGPathContainsPoint。

例子:

func didTapMap(gestureRecognizer: UIGestureRecognizer) {
    let tapPoint: CGPoint = gestureRecognizer.locationInView(map)
    NSLog("tapPoint = %f,%f",tapPoint.x, tapPoint.y)

    let tapCoordinate = map.convertPoint(tapPoint, toCoordinateFromView: map)

    let tapMapPoint = MKMapPointForCoordinate(tapCoordinate)

    for overlay in self.map.overlays{
        if (overlay.isKindOfClass(MKCircle))
        {
            let circle = overlay as MKCircle

            let circleCenterMapPoint = MKMapPointForCoordinate(circle.coordinate)

            let distanceFromCircleCenter = MKMetersBetweenMapPoints(circleCenterMapPoint, tapMapPoint)

            if distanceFromCircleCenter <= circle.radius {
                NSLog("tapped in circle");
                break
            }
        }
    }       
}
Run Code Online (Sandbox Code Playgroud)