7

我正在尝试MKPolylineMKPolylineView. 到目前为止一切都很好 - 折线按照我想要的方式绘制,并且在我想要它的时候使用以下代码:

[[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 的Quick Help部分发现了这个花絮:

MKPolylineView 类为 MKPolyline 注释对象提供可视化表示。此视图描边由注释表示的路径。(该类不会填充路径所包围的区域。)您可以通过修改继承自MKOverlayPathView 类的属性来改变路径的颜色和其他绘制属性。

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

4

4 回答 4

16

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

// 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;
}

请注意,您不需要在此处引用任何类属性,因为覆盖已传递给您的viewForOverlay. 如果您在地图中添加了多个叠加层,这会更加灵活一些。


顺便说一句,这些是我的标准viewForOverlay(iOS 7.0 之前的版本)和rendererForOverlay(iOS 7+),它们将处理MKPolygonMKPolylineMKCircle覆盖:

// 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;
}

通过这种方式,我可以在地图中添加尽可能多的这三种类型的叠加层,并且可以正确渲染所有这些叠加层。

于 2013-02-16T22:21:58.107 回答
2

您可以通过实现自己的 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;
}

或者您可以从以下链接下载代码https://github.com/nighthawk/ASPolylineView

我已经使用它并查看此屏幕截图。

折线的边框颜色

于 2017-03-10T10:04:57.660 回答
1

我有另一种方法。

如果您没有坐标数组,则可以绘制两条折线。

绘制特定 line1_width 的第一行,然后使用 line2_width = line1_width - 1.0 绘制另一行。

这将绘制两条线,在第二条线中,您只会看到它的边距,成为第一条线的笔划。

于 2014-05-28T14:06:32.050 回答
1

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

pointsToUse.reverse()
let overlay = MKPolygon(coordinates: &pointsToUse, count: pointsToUse.count)
于 2016-10-18T23:22:46.897 回答