地图套件:添加MKPolyline隐藏MKTileOverlay



我有一个MKMapView使用显示本地数据库中的磁贴的MKTileOverlay。它工作正常。
然后我用MKDirections来获取两个坐标之间的方向,并像这样绘制路线:

MKRoute *route = response.routes.lastObject;
MKPolyline *polyline = route.polyline;
// Draw path on overlay
[self.mapView insertOverlay:polyline aboveOverlay:self.tileOverlay];

但是当我缩放以查看该行时,它似乎没有磁贴背景(通常从MKTileOverlay加载(存储到 self.tileOverlay 中))。我加入了一个图像,以便看得更清楚。

我还编写了以下代码来渲染叠加层:

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
    if ([overlay isKindOfClass:[MKTileOverlay class]]) {
        return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
    }
    else if ([overlay isKindOfClass:[MKPolyline class]]) {
        MKPolylineRenderer *lineView = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
        lineView.strokeColor = [UIColor greenColor];
        lineView.lineWidth = 3;
        return lineView;
    }
    return nil;
}

这就像渲染线条的"瓷砖"隐藏了从MKTileOverlay加载的瓷砖。我怎样才能 :
- 指定我MKPolyline覆盖必须是透明的?
- 重新加载背景瓷砖?

斯克里肖特 :

看到带线条的瓷砖不再有背景 http://sigmanet.ch/tmp/screen.png

经过几天的工作,这是我自己的解决方案。

扩展MKPolylineRenderer并添加对MKTileOverlayRenderer的引用。我们称这个新类为MCPolylineRenderer

在此类中,重写以下两个方法:

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
    // Draw path only if tile render has a tile
    if ([self.tileRenderRef canDrawMapRect:mapRect zoomScale:zoomScale]) {
        [super drawMapRect:mapRect zoomScale:zoomScale inContext:context];
    }
}
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale {
    // We can draw path only if tile render can also
    return [self.tileRenderRef canDrawMapRect:mapRect zoomScale:zoomScale];
}

现在,在mapView:renderedForOverlay方法中,将

MKPolylineRenderer *lineView = [[MKPolylineRenderer alloc] initWithOverlay:overlay]; 

MCPolylineRenderer *lineView = [[MCPolylineRenderer alloc] initWithPolyline:overlay];
lineView.tileRenderRef = self.tileRender;

此外,还需要确保 loadTileAtPath:result: 方法不会在没有任何要呈现的内容(如"找不到磁贴"图像)时生成磁贴。

此代码将生效,当没有要呈现的背景磁贴时,也不会绘制路径。

您必须对 MKPolylineRenderer 进行子类化以同步渲染器绘制功能。

import Foundation
import MapKit
class MyPolylineRenderer: MKPolylineRenderer {
    var tileRenderer: MKTileOverlayRenderer?
    override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
        if (tileRenderer?.canDraw(mapRect, zoomScale: zoomScale) ?? true) {
            super.draw(mapRect, zoomScale: zoomScale, in: context)
        }
    }
    override func canDraw(_ mapRect: MKMapRect, zoomScale: MKZoomScale) -> Bool {
        return tileRenderer?.canDraw(mapRect, zoomScale: zoomScale) ?? super.canDraw(mapRect, zoomScale: zoomScale)
    }
}

然后在您的MKMapViewDelegate中,保留对 tileRenderer 的引用并实现rendererForOverlay

var tileRenderer: MKTileOverlayRenderer?
public func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    if let polyline = overlay as? MKPolyline {
        let lineRenderer = NXPolylineRenderer(overlay: overlay)
        lineRenderer.tileRenderer = tileRenderer
        // Configure your polyline overlay renderer here...
        return lineRenderer;
    }
    if let tileOverlay = overlay as? MKTileOverlay {
        if tileRenderer == nil || tileRenderer.overlay != overlay {
            tileRenderer = MKTileOverlayRenderer(overlay: overlay)
        }
        return tileRenderer
    }
    return MKOverlayRenderer(overlay: overlay)
}

这个想法的所有功劳都归@Jonathan,我只是发布了一个准备为新手复制/粘贴代码的 swift。

最新更新