如何自定义 MKPolyLineView 绘制不同风格的线条
Posted
技术标签:
【中文标题】如何自定义 MKPolyLineView 绘制不同风格的线条【英文标题】:how to customize MKPolyLineView to draw different style lines 【发布时间】:2011-10-14 12:28:35 【问题描述】:我想自定义在 MKMapView 上绘制的线条以显示路线,以便线条具有边框颜色和填充颜色。与此类似,它有一个黑色边框并用另一种颜色填充:
我目前只是从mapView:viewForOverlay:
返回 MKPolyLineView 对象,这对于纯线效果很好。文档说 MKPolyLineView 不能被子类化,所以我应该将 MKOverlayView 子类化并实现我自己的 drawMapRect 吗?或者我应该继承 MKOverlayPathView?或者为 MKPolylineView 创建一个替代品?
编辑 - 我要问的是:放置你自己的 Quartz 绘图代码以绘制你自己的注释/覆盖的地方在哪里?目前我已经创建了一个 MKOverlayView 的子类并实现了我自己的 drawMapRect:zoomScale:inContext: 以这种方式绘制叠加层非常容易,但这是最好的解决方案吗?
【问题讨论】:
【参考方案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。但我同意,这是一项昂贵的手术。以上是关于如何自定义 MKPolyLineView 绘制不同风格的线条的主要内容,如果未能解决你的问题,请参考以下文章