自定义MKOverlayRenderer drawMapRect函数不绘制多边形

我已经构build了一个自定义MKOverlayRenderer来构build多边形,应用混合模式,然后将它们添加到地图视图中。 在我的drawMapRect函数中,我使用CGPoint数组来构build多边形,并创build一个path。

但是,在运行时没有任何显示在我的地图视图。 我最好的猜测将是我在drawMapRect函数中创build多边形的顺序。 任何帮助或指导将不胜感激,谢谢!

override func drawMapRect(mapRect: MKMapRect, zoomScale: MKZoomScale, inContext context: CGContext) { super.drawMapRect(mapRect, zoomScale: zoomScale, inContext: context) CGContextSaveGState(context) CGContextSetBlendMode(context, CGBlendMode.Exclusion) CGContextSetFillColorWithColor(context, self.fillColor) CGContextSetStrokeColorWithColor(context, UIColor.whiteColor().CGColor) CGContextSetLineWidth(context, 1.0) let point = MKMapPointForCoordinate(self.polygon.points[0]) CGContextMoveToPoint(context, CGFloat(point.x), CGFloat(point.y)) for i in 1..<self.polygon.points.count { let point = polygon.points[i] let p = MKMapPointForCoordinate(point) CGContextAddLineToPoint(context, CGFloat(px), CGFloat(py)) } CGContextClosePath(context) CGContextDrawPath(context, CGPathDrawingMode.FillStroke) CGContextRestoreGState(context) } 

这里是我的自定义覆盖渲染器初始化的地方:

 func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer { if (overlay is MKPolygon) { let polygonRenderer = MyCustomMapRenderer(overlay: overlay, fillColor: self.polyFactory!.getPolygonColor().CGColor, polygon: self.currentPolygon!) return polygonRenderer } return MKOverlayRenderer() } 

几点意见:

  • 你正在采取points ,它已经是一个MKMapPoint数组(至less在MKPolygonRenderer中),并且调用了MKMapPointForCoordinate 。 如果你想使用MKMapPointForCoordinate ,你会传递coordinates ,而不是points 。 也许你已经定义了自己的属性,但我可能会改变属性的名称,以避免混淆。

  • 您需要使用pointForMapPoint将地图点转换为屏幕点。

  • 此外,您正在调用CGContextSetFillColorWithColor ,但传递给fillColor 。 但假设你的类是MKPolygonRenderer的子类, fillColor是一个UIColor ,而不是CGColor

  • 你似乎正在访问一些属性, points ,但MKPolygonRenderer没有points属性,而是points()方法。

所有这些说,我不清楚你的代码甚至编译。 我怀疑你没有从MKPolygonRenderer子类,而是分类MKOverlayRenderer ,然后自己实现了一堆属性? 如果你MKPolygonRender ,你可以免费获得所有的多边形行为,只需要实现drawMapRect

 class MyCustomMapRenderer: MKPolygonRenderer { override func drawMapRect(mapRect: MKMapRect, zoomScale: MKZoomScale, inContext context: CGContext) { //super.drawMapRect(mapRect, zoomScale: zoomScale, inContext: context) CGContextSaveGState(context) CGContextSetBlendMode(context, CGBlendMode.Exclusion) CGContextSetFillColorWithColor(context, fillColor!.CGColor) CGContextSetStrokeColorWithColor(context, UIColor.whiteColor().CGColor) CGContextSetLineWidth(context, 1.0) if polygon.pointCount > 1 { CGContextBeginPath(context) let point = pointForMapPoint(polygon.points()[0]) CGContextMoveToPoint(context, CGFloat(point.x), CGFloat(point.y)) for i in 1 ..< polygon.pointCount { let point = pointForMapPoint(polygon.points()[i]) CGContextAddLineToPoint(context, CGFloat(point.x), CGFloat(point.y)) } CGContextClosePath(context) CGContextDrawPath(context, CGPathDrawingMode.FillStroke) } CGContextRestoreGState(context) } } 

顺便说一下,我们在这里可能会更复杂一些(检查点是否可见,根据比例确定要渲染的点数,即如果具有数千个点的多边形并缩放到视图的100×100部分,也许你不必渲染所有的点等)。 请参阅WWDC 2010 使用叠加层定制地图 ,尽pipe这些地图的date仍然相关。

另外, rendererForOverlay也很好奇。 你正在调用一些自定义的初始化方法(这很好),但你传递overlaycurrentPolygon 。 但overlay 多边形,所以我不知道这个当前多边形什么。 而rendererForOverlay是无状态的,所以我劝阻你引用一些属性,而只是采取传递给方法的overlay 。 这样,你可以有多个多边形,让地图视图跟踪哪个是哪个。 所以我会做这样的事情:

 func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer { if let polygon = overlay as? MKPolygon { let polygonRenderer = MyCustomMapRenderer(polygon: polygon) polygonRenderer.fillColor = polyFactory!.getPolygonColor() return polygonRenderer } fatalError("Unexpected overlay type") } 

Rob在Swift 3中的回答

 class MyRenderer: MKPolylineRenderer { override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) { context.saveGState() context.setBlendMode(CGBlendMode.exclusion) let clear = UIColor.clear context.setFillColor(clear.cgColor) let green = UIColor.green context.setStrokeColor(green.cgColor) context.setLineWidth(10.0) if self.polyline.pointCount > 1 { context.beginPath() let point_ = self.point(for: self.polyline.points()[0]) context.move(to: CGPoint(x: point_.x, y: point_.y)) for element in 1 ..< self.polyline.pointCount { let point_ = self.point(for: polyline.points()[element]) context.addLine(to: CGPoint(x: point_.x, y: point_.y)) } context.closePath() context.drawPath(using: .fillStroke) } context.restoreGState() } }