MKPolylineRenderer产生锯齿状,不相等的路径

时间:2013-12-16 00:39:14

标签: ios ios7 mapkit mkoverlay mkpolyline

我正在使用iOS 7 MapKit API在地图上生成3D相机移动,该地图显示MKDirectionsRequest生成的路径。该路径由MKOverlayRenderer呈现,如下所示:

-(void)showRoute:(MKDirectionsResponse *)response
{
for (MKRoute *route in response.routes)
 {
    [self.map
     addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
 }
}

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay
{
 MKPolylineRenderer *renderer =
 [[MKPolylineRenderer alloc] initWithOverlay:overlay];
UIColor *mapOverlayColor = [UIColor colorWithRed:((float)22 / 255.0f) green:((float)126 / 255.0f) blue:((float)251 / 255.0f) alpha:0.8];
 renderer.strokeColor = mapOverlayColor;
 renderer.lineWidth = 13.0;
 return renderer;
}

除了一个问题外,它运作良好。当我使用MKMapCameras缩放或平移路径时(如果没有它们,如果我只是以用户身份执行),则路径呈锯齿状,如此屏幕截图所示:

screen shot

我测试过看看切换到MKOverlayLevelAboveLabels是否有所作为,但遗憾的是结果是相同的。

有没有人有关于如何改进渲染的建议?切换到测地路径是否会产生影响?如果是这样,我将如何实现此目标?

5 个答案:

答案 0 :(得分:2)

一旦在地图上绘制线条,如果用户缩放,则可能无法重新渲染。或者,如果是,则可以在用户完成缩放之前重新渲染。在这种情况下,缩放后的宽度将不再以米为单位反映所需的宽度。处理此问题的一种方法是覆盖regionDidChangeAnimated并删除叠加层并将其重新添加。

答案 1 :(得分:2)

MKPolylineRenderer严重破坏,因为它不会在屏幕外重绘,并且它具有错误的逻辑来计算其剪裁,这会导致端盖伪像留在屏幕上。删除和读取叠加层对我没有任何帮助。尝试修复线宽确实有效,但是你仍然会遇到更大线宽的端帽问题。使用roadSizeForZoomLevel选项也不会(lineWidth = 0)

为了摆脱永远不会消失的endcap工件,我使用了Breadcrumb示例应用程序中的渲染器。现在我只是在移动地图时偶尔会遇到不可接受的重绘问题。

我认为面包线渲染器是PolylineRenderer应该是什么,但有人打破了它。但即便如此仍然不清楚如何强制屏幕外重绘(我不是核心图形专家,但鉴于苹果地图应用程序没有表现出这种行为,我相信大师可以解决它。

无论如何,如果你至少想要一个不会在屏幕上留下垃圾的渲染器,请使用Breadcrumb渲染器。这是我能找到的最好的。如果你真的需要一个更好的mapkit尝试googmaps

答案 2 :(得分:2)

当缩放变化和区域变化时,MKPolyline不会绘制。简单修复如下。

public class PolylineRenderer : MKPolylineRenderer {

    private var displayLink: CADisplayLink!
    private var ticks = 0

    override public init(overlay: MKOverlay) {
        super.init(overlay: overlay)

        displayLink = CADisplayLink(target: self, selector:#selector(PolylineRenderer._update))
    displayLink.add(to: .main, forMode: .commonModes)
    }

    func _update() {
        if ticks < 3 {
            ticks+=1
        } else {
            ticks = 0
        }

        if ticks == 0 {
            self.setNeedsDisplay()
        }
    }

    deinit {
        if displayLink != nil {
            displayLink.invalidate()
        }
    }
}

一旦你意识到它的绘画速度不够快,它就非常简单了。跳过3个嘀嗒声不会杀死CPU,也不会再遇到麻烦。

答案 3 :(得分:1)

Swift 3解决方案:

创建MKPolylineRenderer的子类

class CustomPolyline: MKPolylineRenderer {

    override func applyStrokeProperties(to context: CGContext, atZoomScale zoomScale: MKZoomScale) {
        super.applyStrokeProperties(to: context, atZoomScale: zoomScale)
        UIGraphicsPushContext(context)
        if let ctx = UIGraphicsGetCurrentContext() {
            ctx.setLineWidth(self.lineWidth)
        }
    }

}

然后在rendererFor MapKit委托中使用它:

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        let renderer = CustomPolyline(overlay: overlay)
        renderer.strokeColor = UIColor.red
        renderer.lineWidth = 100
        return renderer
}

缩放后,折线不会重新渲染,从而避免了瑕疵

答案 4 :(得分:0)

好的,我已经用缓慢的MKPolylineRenderer渲染来解决这个问题。首先使用来自的Breadcrumb渲染器 [Apple面包屑样本] [1] https://developer.apple.com/library/content/samplecode/Breadcrumb/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010048-Intro-DontLinkElementID_2

只需添加您的路径,而不是动态地向CrumpPath添加点。

其次,既然已经修复了MKPolylines错误的渲染,你需要加快速度,因为它的速度非常慢。

请参阅有关堆栈溢出的答案:https://stackoverflow.com/a/28964449/7313127

使其适应&#34; CrumbPathRenderer&#34;只需将这个obj C代码添加到drawMapRect函数中(这只是快速而又脏)

static dispatch_once_t onceToken;

dispatch_once(&amp; onceToken,^ {

    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];

    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
});

在渲染器上创建一个调用setNeedsDisplay

的更新方法

- (void)更新{

[self setNeedsDisplay];

}

我还将renderer.setNeedsDisplay放入(但可能不需要)

func mapView(_ mapView:MKMapView,regionWillChangeAnimated animated:Bool)

{

 crumbRenderer.setNeedsDisplay()

}

重要说明:这将完美呈现,但将使用100%CPU。因此,为了不耗尽手机的电池并使CPU崩溃,在更新方法中保持静态并且每隔三次调用setNeedsDisplay显示链接调用它。记住CA显示链接是硬件刷新计时器。

如果你按照这个(匆忙编写的)答案花了我几天的时间来弄清楚,你将使用大约30%的CPU和你的地图路径从未显示丑陋。

嘿苹果,想修复MKMapView吗?