代码之家  ›  专栏  ›  技术社区  ›  Sam Spencer

绘制MK多段线填充颜色

  •  8
  • Sam Spencer  · 技术社区  · 11 年前

    我正试图画一个漂亮的 MKPolyline MKPolylineView 。到目前为止一切都很顺利-折线可以随心所欲地绘制,也可以在需要时使用以下代码:

    [[self map] addOverlay:routeLine];
    

    这个方法告诉应用程序如何绘制:

    - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
        MKOverlayView* overlayView = nil;
        self.routeLineView = [[MKPolylineView alloc] initWithPolyline:[self routeLine]];
        [[self routeLineView] setFillColor:[UIColor colorWithRed:167/255.0f green:210/255.0f blue:244/255.0f alpha:1.0]];
        [[self routeLineView] setStrokeColor:[UIColor colorWithRed:0/255.0f green:136/255.0f blue:255/255.0f alpha:1.0]];
        [[self routeLineView] setLineWidth:15.0];
        [[self routeLineView] setLineCap:kCGLineCapRound];
        overlayView = [self routeLineView];
        return overlayView;
    }
    

    结果我得到了一条蓝色实线。然而,我看到的蓝色并不是我所期望的笔划的填充颜色,而是笔划颜色中的蓝色。使用此方法时没有填充颜色。 为什么它不在多段线上绘制填充颜色?

    经过进一步调查,我在 快速帮助 Xcode部分:

    MKPolylineView类提供MKPolyline注释对象的视觉表示。此视图绘制由注释表示的路径。( 此类不填充路径所包围的区域 。)可以通过修改从MKOverlayPathView类继承的特性来更改路径的颜色和其他图形属性。

    这听起来很荒谬。我必须利用这门课 设置 填充颜色,但我不能用这个类 填充颜色?考虑到它已经画出了笔画,这似乎很奇怪。文档中的最后一行解释有点不清楚,但似乎提供了一个答案——我只是很难编码/找到答案。我没有 MKOverlayPathView 在我的项目中(那是什么?)但是 这似乎是解决方案——有人知道如何使用它吗?

    4 回复  |  直到 11 年前
        1
  •  17
  •   Rob    11 年前

    如果你想要一条一种颜色的线,另一种填充,使用 MKPolygon 而不是 MKPolyline 。因此,相应地修改您最初创建的注释。然后你修改你的 viewForOverlay (或者对于iOS 7, rendererForOverlay )以识别 MK多边形 并执行以下操作:

    // for iOS7+; see `viewForOverlay` for earlier versions
    
    - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[MKPolygon class]])
        {
            MKPolygonRenderer *renderer = [[MKPolygonRenderer alloc] initWithPolygon:overlay];
    
            renderer.fillColor   = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            renderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            renderer.lineWidth   = 3;
    
            return renderer;
        }
    
        return nil;
    }
    
    // for iOS versions prior to 7; see `rendererForOverlay` for iOS7 and later
    
    - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[MKPolygon class]])
        {
            MKPolygonView *overlayView = [[MKPolygonView alloc] initWithPolygon:overlay];
    
            overlayView.fillColor      = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            overlayView.strokeColor    = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            overlayView.lineWidth      = 3;
    
            return overlayView;
        }
    
        return nil;
    }
    

    注意,您不需要在这里引用任何类属性,因为覆盖会传递给您的 查看覆盖 。如果你在地图上添加了多个覆盖图,这会更灵活一点。


    顺便说一句,这些是我的标准 查看覆盖 (7.0之前的iOS版本)和 用于覆盖的渲染器 (iOS 7+),将处理 MK多边形 , MK多段线 MKCircle 覆盖:

    // for iOS7+; see `viewForOverlay` for earlier versions
    
    - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[MKPolygon class]])
        {
            MKPolygonRenderer *renderer = [[MKPolygonRenderer alloc] initWithPolygon:overlay];
    
            renderer.fillColor   = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            renderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            renderer.lineWidth   = 3;
    
            return renderer;
        }
    
        if ([overlay isKindOfClass:[MKCircle class]])
        {
            MKCircleRenderer *renderer = [[MKCircleRenderer alloc] initWithCircle:overlay];
    
            renderer.fillColor   = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            renderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            renderer.lineWidth   = 3;
    
            return renderer;
        }
    
        if ([overlay isKindOfClass:[MKPolyline class]])
        {
            MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
    
            renderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            renderer.lineWidth   = 3;
    
            return renderer;
        }
    
        return nil;
    }
    
    // for iOS versions prior to 7; see `rendererForOverlay` for iOS7 and later
    
    - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[MKPolygon class]])
        {
            MKPolygonView *overlayView = [[MKPolygonView alloc] initWithPolygon:overlay];
    
            overlayView.fillColor      = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            overlayView.strokeColor    = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            overlayView.lineWidth      = 3;
    
            return overlayView;
        }
    
        if ([overlay isKindOfClass:[MKCircle class]])
        {
            MKCircleView *overlayView = [[MKCircleView alloc] initWithCircle:overlay];
    
            overlayView.fillColor     = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
            overlayView.strokeColor   = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            overlayView.lineWidth     = 3;
    
            return overlayView;
        }
    
        if ([overlay isKindOfClass:[MKPolyline class]])
        {
            MKPolylineView *overlayView = [[MKPolylineView alloc] initWithPolyline:overlay];
    
            overlayView.strokeColor     = [[UIColor blueColor] colorWithAlphaComponent:0.7];
            overlayView.lineWidth       = 3;
    
            return overlayView;
        }
    
        return nil;
    }
    

    通过这种方式,我可以将这三种类型的覆盖添加到我的地图中,并且它可以正确地渲染所有这些覆盖。

        2
  •  2
  •   bphi Michael Garito    6 年前

    您可以通过实现自己的MKOverlayPathView子类来实现这一点,该子类在map rect中绘制两次路径。一次用黑色涂得更厚,一次用另一种颜色涂得更薄。

    我创建了一个简单的替代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;
    }
    

    或者你可以从下面的链接下载它的代码 https://github.com/nighthawk/ASPolylineView

    我用过了,看了一下这个屏幕截图。

    Border color of polyline

        3
  •  1
  •   Teodor Ciuraru    10 年前

    我有了另一种方法。

    如果没有坐标阵列,可以绘制两条多段线。

    绘制特定line1_width的第一条线,然后绘制line2_width=line1_width-1.0的另一条线。

    这将画出两条线,在第二条线中,你只能看到它的边距,成为第一条线的笔划。

        4
  •  1
  •   Mike Onorato    8 年前

    是的,正如Rob提到的,使用MKPolygon和MKPolygonRenderer而不是MKPolyline和MKPolylineRenderer,但也要确保点阵列是顺时针顺序的。如果它是逆时针顺序,您只需要通过对数组调用reverse()来反转它。

    pointsToUse.reverse()
    let overlay = MKPolygon(coordinates: &pointsToUse, count: pointsToUse.count)