我正在使用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缩放或平移路径时(如果没有它们,如果我只是以用户身份执行),则路径呈锯齿状,如此屏幕截图所示:
我测试过看看切换到MKOverlayLevelAboveLabels是否有所作为,但遗憾的是结果是相同的。
有没有人有关于如何改进渲染的建议?切换到测地路径是否会产生影响?如果是这样,我将如何实现此目标?
答案 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吗?