检测地图圆覆盖中的点击始终返回false

时间:2015-02-10 17:20:31

标签: ios swift mapkit

我有一个带有圆形叠加层的地图,它总是从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
            }
        }
    }

}

1 个答案:

答案 0 :(得分:4)

是的,错误的分接点值正传递给CGPathContainsPoint

叠加渲染器path中的值不在屏幕CGPoint单位中。
path包含与渲染器自己的绘图上下文对应的值,该绘图上下文与屏幕不同。

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

MKOverlayRenderer(基类MKCircleRenderer)的方法pointForMapPoint:可以提供帮助,但需要MKMapPoint(不是屏幕CGPoint)。

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

要从屏幕CGPoint转换为MKMapPoint,您需要先使用地图视图CLLocationCoordinate2D将其转换为convertPoint:toCoordinateFromView:,然后使用MKMapPoint函数转到MKMapPointForCoordinate

示例:

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

<小时/> 顺便说一句,使用圆圈,更容易检测其中的点击的方法是计算点击点距圆心的距离。如果分接点距离小于或等于圆的半径,那么它就是圆圈内的一个水龙头。

这样,您就不需要获取圆圈的渲染器,路径或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
            }
        }
    }       
}