检测地图圆覆盖中的点击总是返回 false
detecting tap in map circle overlay always returning false
我有一个带有圆形叠加层的地图,它总是从 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
的基础 class)有方法 pointForMapPoint:
可以提供帮助,但它需要一个 MKMapPoint
(不是屏幕 CGPoint
).
因此您需要将屏幕 CGPoint
转换为 MKMapPoint
,然后最终转换为渲染器上下文中的一个点。
要从屏幕 CGPoint
转换为 MKMapPoint
,您需要先使用地图视图的 convertPoint:toCoordinateFromView:
将其转换为 CLLocationCoordinate2D
,然后再转换为 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
}
}
}
}
我有一个带有圆形叠加层的地图,它总是从 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
的基础 class)有方法 pointForMapPoint:
可以提供帮助,但它需要一个 MKMapPoint
(不是屏幕 CGPoint
).
因此您需要将屏幕 CGPoint
转换为 MKMapPoint
,然后最终转换为渲染器上下文中的一个点。
要从屏幕 CGPoint
转换为 MKMapPoint
,您需要先使用地图视图的 convertPoint:toCoordinateFromView:
将其转换为 CLLocationCoordinate2D
,然后再转换为 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
}
}
}
}