2011-10-14 25 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; 
    } 
} 
相关问题