iOS 原生地图MKMapView上添加图片遮盖物
2016-09-07 本文已影响2039人
踢足球的程序员
未添加遮盖物效果:
WechatIMG2.png
添加遮盖物后效果:
WechatIMG3.png
MKMapView上添加图片遮盖物的原理和添加轨迹的原理基本相同(轨迹可参考上一篇文章),都需要自定义图层(实现MKOverlay协议)和渲染器(继承MKOverlayRenderer)。
CustomOverlay.h实现:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface CustomOverlay : NSObject<MKOverlay>
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, readonly) MKMapRect boundingMapRect;
- (id)initWithRect:(MKMapRect)rect;
@end
CustomOverlay.m实现:
#import "CustomOverlay.h"
@interface CustomOverlay ()
@property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;
@property (nonatomic, readwrite) MKMapRect boundingMapRect;
@end
@implementation CustomOverlay
@synthesize coordinate = _coordinate;
@synthesize boundingMapRect = _boundingMapRect;
#pragma mark - Initalize
- (id)initWithRect:(MKMapRect)rect
{
if (self = [super init])
{
self.boundingMapRect = rect;
}
return self;
}
@end
CustomOverlayRenderer.h实现:
#import <MapKit/MapKit.h>
@interface CustomOverlayRenderer : MKOverlayRenderer
@end
CustomOverlayRenderer.m实现:(注意:绘制image要先转CGImageRef在绘制,网上很多方式甚至高德提供的绘制方法都会让cpu瞬间200%,真机调试用不到5分钟就烫手了。。。)
#import "CustomOverlayRenderer.h"
#import "CustomOverlay.h"
@interface CustomOverlayRenderer ()
@property (nonatomic, strong) UIImage *image;
@end
@implementation CustomOverlayRenderer
- (id) initWithOverlay:(id<MKOverlay>)overlay{
self = [super initWithOverlay:overlay];
if (self){
self.image = [UIImage imageNamed:@"MapHiddenBG.png"];
}
return self;
}
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
@autoreleasepool {
CustomOverlay *overlay = (CustomOverlay *)self.overlay;
if (overlay == nil)
{
NSLog(@"overlay is nil");
return;
}
MKMapRect theMapRect = [self.overlay boundingMapRect];
CGRect theRect = [self rectForMapRect:theMapRect];
// 绘制image
CGImageRef imageReference = self.image.CGImage;
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0.0, -theRect.size.height);
CGContextDrawImage(context, theRect, imageReference);
}
}
@end
类都实现了,剩下的就是正确的在地图上添加我们自定义的图层:(前面那一堆都是计算轨迹在屏幕中显示位置的,也是根我项目相关,可不用理睬)
//设置地图在可见范围
MKMapRect mapRect = MKMapRectNull;
for ( NSDictionary *dic in self.runningData.locationArray) {
CLLocationDegrees latitude = [dic[@"latitude"] doubleValue];
CLLocationDegrees longitude = [dic[@"longitude"] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKMapPoint annotationPoint = MKMapPointForCoordinate(coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
if (MKMapRectIsNull(mapRect)) {
mapRect = pointRect;
} else {
mapRect = MKMapRectUnion(mapRect, pointRect);
}
}
const CGFloat screenEdgeInset = kScreenEdgeInset;
UIEdgeInsets mapInset = UIEdgeInsetsMake(screenEdgeInset, screenEdgeInset, screenEdgeInset*8, screenEdgeInset);
mapRect = [self.mapView mapRectThatFits:mapRect edgePadding:mapInset];
[self.mapView setVisibleMapRect:mapRect edgePadding:mapInset animated:NO];
//添加图片遮盖层
self.mapHiddenImageOverlay = [[CustomOverlay alloc] initWithRect:self.mapView.visibleMapRect];
[self.mapView addOverlay:self.mapHiddenImageOverlay level:1];
添加上了,便会调用rendererForOverlay这个代理方法:(viewForOverlay别实现这个了,这个方法已经标注ios7以后会随时销毁,再信苹果一次,即便很多标注销毁的方法到今天为止也没有几个真正销毁的)
#pragma mark -
#pragma mark - MKMapView Delegate
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay{
if([overlay isKindOfClass:[CustomOverlay class]]){
//遮挡地图图片
CustomOverlayRenderer *renderer = [[CustomOverlayRenderer alloc] initWithOverlay:overlay];
return renderer;
}
return nil;
}
到此,地图上图片遮盖物的功能已经实现了,但美中不足的是CustomOverlayRenderer中drawMapRect是按顺序加载瓦砾,也就是一块一块绘制,性能不好的手机上瓦砾的加载效果还是很明显的,暂时还没找到一次性绘制整张图片的方法,求指点~