ios - 检测 map 圆覆盖中的点击总是返回 false

标签 ios swift mapkit

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

}

最佳答案

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

覆盖渲染器的 path 中的值不是屏幕 CGPoint 单位。
path 包含与渲染器自身的绘图上下文相对应的值,该上下文不同于屏幕。

您需要先将点击点(屏幕 CGPoint)转换为渲染器绘图上下文中的点。

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

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

要从屏幕 CGPoint 转换为 MKMapPoint,您需要先使用 map View 的 将其转换为 CLLocationCoordinate2D convertPoint:toCoordinateFromView:,然后使用 MKMapPointForCoordinate 函数转换为 MKMapPoint

例子:

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

关于ios - 检测 map 圆覆盖中的点击总是返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28437852/

相关文章:

android - 将数据存储在 sql 数据库与数组(移动应用程序)上

objective-c - iap - 从 objective c 到 swift 的转换

ios - 自定义 Apple map 注释无法正常工作

ios - 使用 geocoder.geocodeAddressString 添加多个注释(递归?)

ios - iOS 应用程序的功耗

ios - UITableView 在每个单元格中显示数组中的最后一项

iphone - iOS - 代码仅在插入断点时才有效

ios - Typhoon DI 的 Storyboard集成

xcode - SpriteKit 的更新函数 : time vs. framerate

ios - Apple iOS MapKit 提供了哪些标准注释?