2013-12-16 45 views
9

我正在使用iOS 7 MapKit API在顯示MKDirectionsRequest生成的路徑的地圖上生成3D相機移動。路徑由MKOverlayRenderer渲染,如下所示:MKPolylineRenderer生成鋸齒狀,不等長的路徑

-(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 http://f.cl.ly/items/3L0s3h0B1v113y3O2p3K/iPhone%20Dec%2015,%202013,%207%3A26%3A33%20PM.png

我測試,看是否切換到MKOverlayLevelAboveLabels有所作爲,但可悲的是結果是一樣的。

有沒有人有如何改善渲染的建議?切換到測地路徑會產生什麼影響嗎?如果是這樣,我將如何在此實現這一點?

+0

切換到MKGeodesicPolyline不會使一個不同ENCE但它的創建一樣MKPolyline除非你叫polylineWithXXX上MKGeodesicPolyline但是渲染仍然MKPolylineRenderer。 – Anna

回答

2

一旦線條在地圖上繪製,如果用戶放大,它可能不會被重新渲染。或者,如果是這樣,它可能會在用戶完成縮放之前重新渲染。在這種情況下,縮放後的寬度將不再以米爲單位反映所需的寬度。解決這個問題的一種方法是覆蓋regionDidChangeAnimated並刪除疊加層並將其添加回去。

3

子類MKPolylineRenderer並重寫applyStrokePropertiesToContext:atZoomScale:使得它忽略規模,並以恆定的寬度繪製線條:

@interface ConstantWidthPolylineRenderer : MKPolylineRenderer 
@end 

@implementation ConstantWidthPolylineRenderer 

- (void)applyStrokePropertiesToContext:(CGContextRef)context 
          atZoomScale:(MKZoomScale)zoomScale 
{ 
    [super applyStrokePropertiesToContext:context atZoomScale:zoomScale]; 
    CGContextSetLineWidth(context, self.lineWidth); 
} 

@end 

立即使用它並欣賞它的光滑渲染:

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay 
{ 
    MKPolyline *polyline = (MKPolyline *)overlay; 
    ConstantWidthPolylineRenderer *renderer = [[ConstantWidthPolylineRenderer alloc] initWithPolyline:polyline]; 
    renderer.strokeColor = [UIColor redColor]; 
    renderer.lineWidth = 40; 
    return renderer; 
} 
+1

該解決方案將只有靜態的線寬,所以就當我們做一個水平之後變焦/捏線將不可見相關變焦 - 的問題。 – Kumar

1

MKPolylineRenderer被嚴重破壞,因爲它不會重新脫離屏幕,並且它具有計算其剪輯的錯誤邏輯,這會導致在屏幕上留下末端僞像。刪除和讀取疊加層對我沒有任何幫助。試圖修復線寬可行,但您仍然會遇到較大線寬的端蓋問題。使用roadSizeForZoomLevel選項不會工作(lineWidth = 0)

爲了擺脫永不消失的endcap構件,我使用了Breadcrumb示例應用程序中的渲染器。現在,當移動地圖時,偶爾會出現不可接受的重繪問題。

我認爲這是PolylineRenderer應該是什麼但有人打破了它的麪包屑渲染。但即使仍然不清楚如何強制屏幕重繪(我不是一個核心的圖形專家,但鑑於蘋果地圖應用程序不表現出這種行爲我敢肯定,一個古茹可以弄明白)

無論如何,如果你至少想要一個渲染器如果你真的需要更好的mapkit,請嘗試googmaps

0

好的,我已經解決了慢速MKPolylineRenderer渲染緩慢的問題,首先使用Breadcrumb(麪包屑渲染器)來自 的渲染器[Apple breadcrumb sample] [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

要適應這個以「CrumbPathRenderer」只需添加這OBJ C代碼到drawMapRect功能(這只是快速和骯髒的)

靜態dispatch_once_t onceToken;

dispatch_once(& onceToken,^ {

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

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

上創建調用setNeedsDisplay

渲染器更新方法 - (無效)更新{

[self setNeedsDisplay]; 

}

我也把renderer.setNeedsDisplay(但它也許根本需要)

FUNC MapView類(_ MapView類:的MKMapView,regionWillChangeAnimated動畫:布爾)

{

crumbRenderer.setNeedsDisplay() 

}

重要提示:這將完美呈現,但將使用100 % 中央處理器。因此,爲了不浪費電話的電池和CPU,在更新方法中保持一個靜態和唯一的調用setNeedsDisplay每三次顯示鏈接調用它。記住CA顯示鏈接是一個硬件刷新計時器。

如果按照這花了我幾天要弄清楚這個(急急組成)的答案,你會用約30%的CPU和你的貼圖路徑與從未露面難看。

喂蘋果,想解決的MKMapView?

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並且不會再向鋸齒by by。

1

斯威夫特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 
} 

您的折線不會變焦後重新渲染這樣就避免了工件