【问题标题】:how to customize MKPolyLineView to draw different style lines如何自定义 MKPolyLineView 绘制不同风格的线条
【发布时间】:2011-10-14 12:28:35
【问题描述】:

我想自定义在 MKMapView 上绘制的线条以显示路线,以便线条具有边框颜色和填充颜色。与此类似,它有一个黑色边框并用另一种颜色填充:

我目前只是从mapView:viewForOverlay: 返回 MKPolyLineView 对象,这对于纯线效果很好。文档说 MKPolyLineView 不能被子类化,所以我应该将 MKOverlayView 子类化并实现我自己的 drawMapRect 吗?或者我应该继承 MKOverlayPathView?或者为 MKPolylineView 创建一个替代品?

编辑 - 我要问的是:放置你自己的 Quartz 绘图代码以绘制你自己的注释/覆盖的地方在哪里?目前我已经创建了一个 MKOverlayView 的子类并实现了我自己的 drawMapRect:zoomScale:inContext: 以这种方式绘制叠加层非常容易,但这是最好的解决方案吗?

【问题讨论】:

    标签: iphone ios cocoa-touch mkmapview overlay


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      您可以只添加两个坐标相同但粗细不同的 MKPolyLineView 对象。

      添加一个 lineWidth 为 10(或其他)的,strokeColor 设置为黑色。

      然后添加另一个 lineWidth 为 6 的 strokeColor 设置为您想要的其他颜色。

      您可以对两个 MKPolyLineView 对象使用相同的 MKPolyLine。

      【讨论】:

      • 嗯,好主意,只需确保较宽的折线位于较细的折线下方。
      • 好主意,也许您可​​以将较细的折线添加为较宽的折线的子视图?由于 MKPolyLineView 从 UIView 扩展而来,这在理论上是可能的......
      • 你可以这样做,但是你需要偏移子视图的坐标,这意味着不共享 MKPolyLine。如果您希望它们一起转换,最好让它们成为父 UIView 对象的子对象。
      【解决方案3】:

      MKPolylineView 只能用于描边指定路径。您可以使用MKOverlayPathView 中的一些属性来更改它们的外观,但只有其中一些会适用,例如fillColor, strokeColor.

      如果你想画更复杂的东西,你可以使用MKOverlayPathView。它更通用,因此不仅适用于抚摸路径。对于绘制简单的线条,结果将与MKPolylineView 相同(至少,根据文档)。

      如果你想做更复杂的绘图,子类MKOverlayPathView。您正在尝试做的事情并非微不足道。

      【讨论】:

        【解决方案4】:

        我使用了一个名为 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;
            }
        }
        

        【讨论】:

          【解决方案5】:

          我知道这可能与您想要的纯方法不匹配,但为什么不使用 MKPolygon 而不是 MKPolyLine 呢?
          创建一个MKPolygon 实例,它代表一种您的路线周围的走廊,然后,当您创建与您的MKPolygon/corridor 相对应的MKPolygonView创建后,设置MKPolygonView的属性,得到不同的填充颜色和描边颜色

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

          我自己没有尝试过,但这应该可以。唯一的缺点是当你放大/缩小时,'路线'的'宽度'会改变......:/

          【讨论】:

          • 好主意,但是从任意一组路线坐标计算多边形的边界非常复杂
          • 一种基本的做法是,走廊上部的纬度加0.000001,下部的纬度加-0.000001,然后用上下两部分组成的多边形构建走廊。 ..只是一个想法...
          • 这只有在路线沿东/西方向运行时才有效。这些可以在任何方向上运行,因此多边形需要基于每条线段的方向。侧面需要与路线航向成直角,并且使用 Spherical Law of Cosines 从纬度/经度对计算航向是一项昂贵的操作。
          • 在 GIS 中,这可以使用 ST_BUFFER postgis.org/docs/ST_Buffer.html 来实现。如果你的 iPhone 上有 spaceite,你也可以通过 1 次调用来计算它:gaia-gis.it/spatialite-2.4.0-4/spatialite-sql-2.4-4.html。但我同意,这是一项昂贵的手术。
          猜你喜欢
          • 2012-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-02
          • 1970-01-01
          • 2011-06-07
          • 1970-01-01
          相关资源
          最近更新 更多