2011-10-14 24 views
9

我想自定義在MKMapView上繪製的線條以顯示路線,以便線條具有邊框顏色和填充顏色。與此相似的地方有一個黑色的邊框和充滿另一種顏色:如何自定義MKPolyLineView以繪製不同的樣式線

blue line with black border

我目前剛剛返回MKPolyLineView從mapView:viewForOverlay:工作正常進行簡單的線條對象。文檔說MKPolyLineView不被子類化,所以我應該繼承MKOverlayView並實現我自己的drawMapRect?或者我應該繼承MKOverlayPathView?或者創建一個MKPolylineView的替代品?

編輯 - 我問的是:在哪裏放置自己的Quartz繪圖代碼以繪製自己的註釋/覆蓋圖?目前我已經創建了一個MKOverlayView的子類並實現了我自己的drawMapRect:zoomScale:inContext:這樣繪製覆蓋圖非常容易,但這是最好的解決方案嗎?

回答

12

您可以通過實現您自己的MKOverlayPathView子類來完成此操作,該子類在地圖矩形中繪製兩次路徑。一旦黑色變厚,另一種顏色再變薄一次。

我已經創建了一個簡單的MKPolylineView的替代方案,它可以讓你這麼做:ASPolylineView

如果你想自己做,你需要實現兩種主要方法看起來是這樣的:

- (void)drawMapRect:(MKMapRect)mapRect 
      zoomScale:(MKZoomScale)zoomScale 
      inContext:(CGContextRef)context 
{ 
    UIColor *darker = [UIColor blackColor]; 
    CGFloat baseWidth = self.lineWidth/zoomScale; 

    // draw the dark colour thicker 
    CGContextAddPath(context, self.path); 
    CGContextSetStrokeColorWithColor(context, darker.CGColor); 
    CGContextSetLineWidth(context, baseWidth * 1.5); 
    CGContextSetLineCap(context, self.lineCap); 
    CGContextStrokePath(context); 

    // now draw the stroke color with the regular width 
    CGContextAddPath(context, self.path); 
    CGContextSetStrokeColorWithColor(context, self.strokeColor.CGColor); 
    CGContextSetLineWidth(context, baseWidth); 
    CGContextSetLineCap(context, self.lineCap); 
    CGContextStrokePath(context); 

    [super drawMapRect:mapRect zoomScale:zoomScale inContext:context]; 
} 

- (void)createPath 
{ 
    // turn the polyline into a path 

    CGMutablePathRef path = CGPathCreateMutable(); 
    BOOL pathIsEmpty = YES; 

    for (int i = 0; i < self.polyline.pointCount; i++) { 
     CGPoint point = [self pointForMapPoint:self.polyline.points[i]]; 

     if (pathIsEmpty) { 
      CGPathMoveToPoint(path, nil, point.x, point.y); 
      pathIsEmpty = NO; 
     } else { 
      CGPathAddLineToPoint(path, nil, point.x, point.y); 
     } 
    } 

    self.path = path; 
} 
1

我知道這可能不符合您想要的純粹方法,但爲什麼不使用MKPolygon而不是MKPolyLine
創建MKPolygon實例代表了一種走廊的路線四周,然後,當你創建一個對應於您所創建的MKPolygon /走廊MKPolygonView,設置MKPolygonView的屬性,以獲得不同填充顏​​色和筆觸顏色

myPolygonView.lineWidth=3; 
    myPolygonView.fillColor=[UIColor blueColor]; 
    myPolygonView.strokeColor=[UIColor darkGrayColor]; 

我沒有嘗試它自己,但這應該工作。唯一的缺點是,當你放大/縮小時,'路線'的'寬度'將改變....:/

+0

不錯的主意,但計算多邊形的從邊界一組任意的路線座標相當複雜 – progrmr

+0

一個基本的方法可能是在走廊的上部加上0.000001的緯度,然後在下部加上-0.000001,然後建立一個由上下兩部分組成的多邊形的走廊零件...只是一個想法... – yonel

+0

這隻會在路線沿東/西方向運行時起作用。這些可以在任何方向上運行,因此多邊形需要基於每個線段的標題。邊需要與路線標題成直角,並使用[餘弦的球面法則]計算經緯度對的方向(http://stackoverflow.com/questions/6924742/valid-way-to-計算角度在2-cllocations/7352235#7352235)是一個昂貴的操作。 – progrmr

4

您可以添加兩個具有相同座標但厚度不同的MKPolyLineView對象。

添加一個lineWidth爲10(或任何)與strokeColor設置爲黑色。

然後添加另一個lineWidth爲6的strokeColor設置爲其他所需的顏色。

對於兩個MKPolyLineView對象,可以使用相同的MKPolyLine。

+0

嗯,好主意,只要確保更寬的折線在更細的折線下。 – progrmr

+0

不錯的想法,也許你可以添加更薄的折線作爲更廣泛的子視圖?因爲MKPolyLineView從UIView擴展而來,這在理論上是可能的...... – yonel

+0

你可以這樣做,但是你需要抵消子視圖的座標,這意味着不共享MKPolyLine。如果您希望它們一起轉換,最好讓它們成爲父UIView對象的子項。 – MindJuice

2

MKPolylineView只能用於撫摸指定的路徑。您可以使用MKOverlayPathView中的一些屬性來改變它們的外觀,但僅適用其中的一些屬性,例如, fillColor,strokeColor

如果你想繪製更復雜的東西,你可以使用MKOverlayPathView。它更通用,因此不僅適用於撫摸路徑。爲了繪製簡單的線條,結果將與MKPolylineView相同(至少根據文檔)。

如果你想做更復雜的繪圖,子類MKOverlayPathView。你試圖做的是不平凡的。

2

我用一個保存了覆蓋一個名稱的子類NamedOverlay:

NamedOverlay.h

#import <Foundation/Foundation.h> 
#import <MapKit/MapKit.h> 

@interface NamedOverlay : NSObject <MKOverlay> 

@property (strong, readonly, nonatomic) NSString *name; 
@property (strong, readonly, nonatomic) id<MKOverlay> overlay; 

-(id)initWithOverlay:(id<MKOverlay>)overlay andName:(NSString *)name; 

@end 

NamedOverlay.m

#import "NamedOverlay.h" 

@implementation NamedOverlay 

- (id)initWithOverlay:(id<MKOverlay>)overlay andName:(NSString *)name 
{ 
    _name = name; 
    _overlay = overlay; 
    return self; 
} 

- (MKMapRect)boundingMapRect 
{ 
    return [_overlay boundingMapRect]; 
} 

- (CLLocationCoordinate2D)coordinate 
{ 
    return [_overlay coordinate]; 
} 

-(BOOL)intersectsMapRect:(MKMapRect)mapRect 
{ 
    return [_overlay intersectsMapRect:mapRect]; 
} 

@end 

,並在地圖控制器我實例化兩個貼有不同的名稱,然後在MKMapViewDelegate我可以確定我想提請其覆蓋,並完成類似:

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay 
{ 
    NamedOverlay *namedOverlay = (NamedOverlay *) overlay; 
    MKPolyline *polyline = namedOverlay.overlay; 
    if ([namedOverlay.name isEqualToString:@"top"]) { 
     MKPolylineView *view1 = [[MKPolylineView alloc] initWithOverlay:polyline]; 
     view1.strokeColor = [UIColor whiteColor]; 
     view1.lineWidth = 25.0; 
     return view1; 
    } else { 
     MKPolylineView *view1 = [[MKPolylineView alloc] initWithOverlay:polyline]; 
     view1.strokeColor = [UIColor blueColor]; 
     view1.lineWidth = 15.0; 
     return view1; 
    } 
} 
相關問題