2013-12-16 11 views
9

私は、MKDirectionsRequestで生成されたパスを表示するマップ上で3Dカメラの動きを生成するために、iOS 7 MapKit APIを使用しています。パスは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; 
} 

1つの問題を除いてうまくいきます。 (私は単にユーザーとしてそうするならば、そしてそれらなし)私はMKMapCamerasとパスを中心にズームやパンすると、このスクリーンショットのように、パスがギザギザである:

screen shot http://f.cl.ly/items/3L0s3h0B1v113y3O2p3K/iPhone%20Dec%2015,%202013,%207%3A26%3A33%20PM.png

私は、スイッチングかどうかを確認するためにテストMKOverlayLevelAboveLabelsには違いはありますが、残念ながら結果は同じでした。

レンダリングの改善方法に関する提案はありますか?測地線パスに切り替えると違いがありますか?もしそうなら、私はこれをどのように実装しますか?

+0

MKGeodesicPolylineに切り替えることで違いはありませんMKGolodesicPolyline上でpolylineWithXXXを呼び出すことを除いてMKPolylineと同じ方法で作成されますが、レンダラーはまだMKPolylineRendererです。 – Anna

答えて

2

地図上に線が描画されると、ユーザーがズームすると再レンダリングされないことがあります。または、そうであれば、ユーザーがズームを終了する前に再描画されることがあります。この場合、ズーム後の幅は希望の幅をメートルで反映しなくなります。これに対処する1つの方法は、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画面外で再描画されず、エンドキャップアーチファクトを画面上に残すようにクリップ直しを計算するための論理が間違っているため、真剣に壊れています。オーバーレイを削除して読み込むことは、私のために何もしなかった。線幅を修正しようとしても問題はありませんが、線幅が大きいほどエンドキャップの問題が発生します。 (lineWidth = 0)

私は遠く離れていないエンドキャップアーチファクトを取り除くために、ブレッドクラムサンプルアプリからレンダラーを使用しました。今度は地図を動かすときに時々受け入れられない再描画の問題があります。

私が思うのは、PolylineRendererがそうなっていたものの、誰かがそれを壊したと思います。しかし、それでも明らかにオフスクリーンレンダリングを強制する方法はありません(コアグラフィックスのエキスパートではありませんが、リンゴマップのアプリケーションではこの動作が示されません)。

レンダラー

0

OK、ゆっくりと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はパスを追加するだけです。

第2に、MKPolylinesの欠陥レンダリングを修正したので、恐ろしく遅いので、スピードアップする必要があります。

スタックオーバーフローにこの回答を参照してください:https://stackoverflow.com/a/28964449/7313127

だけdrawMapRect機能に、これはCコードをobjを追加し、「CrumbPathRenderer」にこれを適合させるため(これは、単に迅速かつ汚いです)

静的dispatch_once_t onceToken。 (ボイド)更新{

[self setNeedsDisplay]; 

}

-

dispatch_once(& onceToken、^ {

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

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

はsetNeedsDisplay

を呼び出しレンダラに更新メソッドを作成します私はまた、renderer.setNeedsDisplayを入れます(ただし、おそらく必要ないS)

にfuncのMapView(_のMapView:ブール値)

{

crumbRenderer.setNeedsDisplay() 

}

重要注:MKMapViewは、アニメーションをregionWillChangeAnimatedこれは完璧にレンダリングされますが、100を使用します。 % CPU。したがって、携帯電話のバッテリーを使い切ってCPUをスラッシュしないようにするには、更新メソッドで静的なコールを維持し、setNeedsDisplayを3回目の表示リンクで呼び出します。 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やジャグジーが壊れることはありません。

1

スウィフト3溶液:

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

あなたのポリラインは、ズーム後に再表示されません。

があなたのrendererFor MapKitデリゲートでそれを使用すると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) 
     } 
    } 

} 

のサブクラスを作成します。したがって、アーティファクトを回避する