地圖的基本使用
-
1.設(shè)置地圖顯示類型
// 1.設(shè)置地圖顯示類型 /** MKMapTypeStandard = 0, // 標(biāo)準(zhǔn) MKMapTypeSatellite, // 衛(wèi)星 MKMapTypeHybrid, // 混合(標(biāo)準(zhǔn)+衛(wèi)星) MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0), // 3D立體衛(wèi)星 MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0), // 3D立體混合 */ self.customMapView.mapType = MKMapTypeStandard;
-
設(shè)置地圖的其他屬性(操作項(xiàng))
- 注意:設(shè)置對(duì)應(yīng)屬性時(shí)喊巍,注意該屬性是從哪個(gè)系統(tǒng)版本開(kāi)始引入的夹孔,做好不同系統(tǒng)版本的適配
// 是否可以縮放 self.customMapView.zoomEnabled = NO; // 是否可以滾動(dòng) self.customMapView.scrollEnabled = NO; // 是否可以旋轉(zhuǎn) self.customMapView.rotateEnabled = NO; // 是否顯示3D self.customMapView.pitchEnabled = NO;
- 注意:設(shè)置對(duì)應(yīng)屬性時(shí)喊巍,注意該屬性是從哪個(gè)系統(tǒng)版本開(kāi)始引入的夹孔,做好不同系統(tǒng)版本的適配
-
設(shè)置地圖其他屬性
// 是否顯示指南針 self.customMapView.showsCompass = YES; // 是否顯示比例尺 self.customMapView.showsScale = YES; // 是否顯示交通 self.customMapView.showsTraffic = YES; // 是否顯示建筑物 self.customMapView.showsBuildings = YES;
-
設(shè)置地圖的用戶追蹤模式
- 1.創(chuàng)建CLLocationManager對(duì)象請(qǐng)求授權(quán)
-(CLLocationManager *)locationM
{
if (!_locationM) {
_locationM = [[CLLocationManager alloc] init];
if ([_locationM respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[_locationM requestAlwaysAuthorization];
}
}
return _locationM;
}
```
- 2.設(shè)置地圖的用戶追蹤模式
```objc
/**
MKUserTrackingModeNone = 0, // 不跟隨
MKUserTrackingModeFollow, // 跟隨用戶位置
MKUserTrackingModeFollowWithHeading, // 跟隨用戶位置汁展,并跟隨用戶方向
*/
[self locationM];
self.customMapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
```
地圖中級(jí)使用
- 查看當(dāng)前用戶位置信息
- 1.設(shè)置地圖代理,并實(shí)現(xiàn)代理方法穆役,在代理方法中獲取用戶當(dāng)前位置(注意iOS8.0之后要請(qǐng)求授權(quán))
- 2.將地圖顯示中心調(diào)整為用戶當(dāng)前所在位置(iOS之前,地圖不會(huì)自動(dòng)移動(dòng)到用戶所在位置)
- 3.調(diào)整當(dāng)前地圖顯示的區(qū)域(可使用對(duì)應(yīng)代理方法查看當(dāng)前地圖跨度然后調(diào)整到合適的跨度即可)
-(void)mapView:(MKMapView )mapView didUpdateUserLocation:(MKUserLocation )userLocation
{
/
MKUserLocation : 被稱作“大頭針模型”梳凛,其實(shí)喊什么都行耿币,本質(zhì)就是一個(gè)數(shù)據(jù)模型,只不過(guò)此模型遵循了大頭針要遵循的協(xié)議(MKAnnotation)
location: 用戶當(dāng)前所在位置信息(CLLocation對(duì)象)
title: 大頭針標(biāo)注要顯示的標(biāo)題(NSString對(duì)象)
subtitle: 大頭針標(biāo)注要顯示的子標(biāo)題(NSString對(duì)象)
/
// 根據(jù)用戶當(dāng)前位置的經(jīng)緯度韧拒,設(shè)置地圖顯示中心
/*
存在弊端:地圖顯示比例過(guò)大淹接,無(wú)法調(diào)整
解決方案:直接使用對(duì)應(yīng)的調(diào)整地圖“顯示區(qū)域”的API
/
// [mapView setCenterCoordinate:userLocation.coordinate animated:YES];
/*
MKCoordinateSpan 跨度解釋:
latitudeDelta:緯度跨度,因?yàn)槟媳本暩?0度叛溢,所以此值的范圍是(0---180)塑悼;此值表示,整個(gè)地圖視圖寬度楷掉,顯示多大跨度
longitudeDelta:經(jīng)度跨度厢蒜,因?yàn)闁|西經(jīng)各180度,所以此值范圍是(0---360):此值表示烹植,整個(gè)地圖視圖高度斑鸦,顯示多大跨度
注意:地圖視圖顯示,不會(huì)更改地圖的比例草雕,會(huì)以地圖視圖高度或?qū)挾容^小的那個(gè)為基準(zhǔn)巷屿,按比例調(diào)整
*/
// MKCoordinateSpan span = MKCoordinateSpanMake(0.1, 0.1);
// MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.coordinate, span);
// [mapView setRegion:region animated:YES];
}
// 當(dāng)?shù)貓D區(qū)域(跨度)改變時(shí)調(diào)用
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
NSLog(@"%f---%f", mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta);
}
```
大頭針基本使用
- 在地圖上操作大頭針,實(shí)際上就是操作大頭針數(shù)據(jù)模型
- 添加大頭針就是添加大頭針數(shù)據(jù)模型
- 刪除大頭針就是刪除大頭針模型
- 實(shí)現(xiàn)步驟
-
添加一個(gè)/多個(gè)大頭針
- 1.自定義大頭針模型(需要遵循MKAnnotation協(xié)議)
#import <MapKit/MapKit.h>
@interface XMGAnnotation : NSObject <MKAnnotation>
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy, nullable) NSString *title;
@property (nonatomic, copy, nullable) NSString *subtitle;@end
```- 2.創(chuàng)建自定義大頭針模型墩虹,并添加到地圖上
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 如果我們僅僅添加大頭針數(shù)據(jù)模型嘱巾,地圖上會(huì)自動(dòng)添加系統(tǒng)默認(rèn)的大頭針視圖
CYXAnnotation *annotation = [[CYXAnnotation alloc] init];
// annotation.coordinate = self.mapView.centerCoordinate;
// 1. 獲取當(dāng)前點(diǎn)的位置
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.mapView];
// 把點(diǎn)轉(zhuǎn)換成對(duì)應(yīng)的經(jīng)緯度
CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
// TODO:使用反地理編碼,獲取對(duì)應(yīng)大頭針的所在的位置信息败晴,通過(guò)標(biāo)注顯示出來(lái)
annotation.coordinate = coordinate;
annotation.title = @"荔灣區(qū)";
annotation.subtitle = @"和業(yè)廣場(chǎng)";// 添加單個(gè)大頭針 [self.mapView addAnnotation:annotation]; // 添加多個(gè)大頭針
// [self.mapView addAnnotations:@[]];
}
```- 移除1個(gè)/多個(gè)大頭針
[self.mapView removeAnnotations:self.mapView.annotations];
- 1.自定義大頭針模型(需要遵循MKAnnotation協(xié)議)
-
自定義大頭針
- 添加大頭針數(shù)據(jù)時(shí)浓冒,其實(shí)地圖會(huì)調(diào)用代理方法查找對(duì)應(yīng)的大頭針視圖,如果沒(méi)有找到尖坤,就會(huì)使用系統(tǒng)默認(rèn)的大頭針視圖
- 1.模擬系統(tǒng)大頭針實(shí)現(xiàn)方案稳懒,并對(duì)大頭針進(jìn)行部分自定義
- (彈出標(biāo)注, 修改大頭針顏色, 設(shè)置大頭針從天而降场梆, 設(shè)置大頭針可以被拖拽)
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if ([annotation isKindOfClass:[MKUserLocation class]]) { return nil; } // 如果此方法返回nil, 就會(huì)使用系統(tǒng)自帶的大頭針視圖 // 模擬下墅冷,返回nil,系統(tǒng)的解決方案 static NSString *pinId = @"pinID"; MKPinAnnotationView *pinView = ( MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pinId]; if (pinView == nil) { pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinId]; } pinView.annotation = annotation; // 是否顯示標(biāo)注 pinView.canShowCallout = YES; // 設(shè)置大頭針顏色 pinView.pinColor = MKPinAnnotationColorPurple; // 設(shè)置大頭針是否有下落動(dòng)畫 pinView.animatesDrop = YES; return pinView; }
- 2.自定義大頭針
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if ([annotation isKindOfClass:[MKUserLocation class]]) { return nil; } /** 自定義大頭針-------*/ static NSString *pinId = @"pinID"; MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:pinId]; if (annoView == nil) { annoView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinId]; } annoView.annotation = annotation; annoView.image = [UIImage imageNamed:@"category_5"]; annoView.canShowCallout = YES; UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"huba.jpeg"]]; imageView.bounds = CGRectMake(0, 0, 44, 44); annoView.leftCalloutAccessoryView = imageView; imageView.userInteractionEnabled = YES; UIImageView *imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eason.jpg"]]; imageView2.bounds = CGRectMake(0, 0, 44, 44); annoView.rightCalloutAccessoryView = imageView2; annoView.detailCalloutAccessoryView = [UISwitch new]; annoView.draggable = YES; return annoView; }
大頭針圖標(biāo)或油,大頭針標(biāo)注寞忿,左側(cè)視圖,右側(cè)視圖顶岸,詳情視圖腔彰,等;
```
- 選中和取消選中大頭針時(shí)的代理方法
```objc
// 點(diǎn)擊標(biāo)注
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(@"點(diǎn)擊標(biāo)注");
}
// 選中大頭針
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
NSLog(@"選中大頭針");
}
// 取消選中大頭針
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
NSLog(@"取消選中大頭針");
}
```
利用系統(tǒng)App導(dǎo)航
// 根據(jù)兩個(gè)地標(biāo)對(duì)象進(jìn)行調(diào)用系統(tǒng)導(dǎo)航
- (void)beginNavWithBeginPlacemark:(CLPlacemark *)beginPlacemark andEndPlacemark:(CLPlacemark *)endPlacemark
{
// 根據(jù) CLPlacemark 地標(biāo)對(duì)象創(chuàng)建 MKPlacemark 地標(biāo)對(duì)象
MKPlacemark *itemP1 = [[MKPlacemark alloc] initWithPlacemark:beginPlacemark];
MKMapItem *item1 = [[MKMapItem alloc] initWithPlacemark:itemP1];
MKPlacemark *itemP2 = [[MKPlacemark alloc] initWithPlacemark:endPlacemark];
MKMapItem *item2 = [[MKMapItem alloc] initWithPlacemark:itemP2];
NSDictionary *launchDic = @{
// 設(shè)置導(dǎo)航模式參數(shù)
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
// 設(shè)置地圖類型
MKLaunchOptionsMapTypeKey : @(MKMapTypeHybridFlyover),
// 設(shè)置是否顯示交通
MKLaunchOptionsShowsTrafficKey : @(YES),
};
// 根據(jù) MKMapItem 數(shù)組 和 啟動(dòng)參數(shù)字典 來(lái)調(diào)用系統(tǒng)地圖進(jìn)行導(dǎo)航
[MKMapItem openMapsWithItems:@[item1, item2] launchOptions:launchDic];
}
數(shù)字版街景地圖
/**
補(bǔ)充1:類似于地圖街景辖佣,增強(qiáng)用戶體驗(yàn)
*/
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(23.132931, 113.375924);
MKMapCamera *camera = [MKMapCamera cameraLookingAtCenterCoordinate:center fromEyeCoordinate:CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001) eyeAltitude:1];
self.mapView.camera = camera;
地圖快照截圖
/**
補(bǔ)充2:地圖截圖
*/
// 截圖附加選項(xiàng)
MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
// 設(shè)置截圖區(qū)域(在地圖上的區(qū)域,作用在地圖)
options.region = self.mapView.region;
// options.mapRect = self.mapView.visibleMapRect;
// 設(shè)置截圖后的圖片大小(作用在輸出圖像)
options.size = self.mapView.frame.size;
// 設(shè)置截圖后的圖片比例(默認(rèn)是屏幕比例霹抛, 作用在輸出圖像)
options.scale = [[UIScreen mainScreen] scale];
MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithCompletionHandler:^(MKMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
if (error) {
NSLog(@"截圖錯(cuò)誤:%@",error.localizedDescription);
}else
{
// 設(shè)置屏幕上圖片顯示
self.snapshootImageView.image = snapshot.image;
// 將圖片保存到指定路徑(此處是桌面路徑,需要根據(jù)個(gè)人電腦不同進(jìn)行修改)
NSData *data = UIImagePNGRepresentation(snapshot.image);
[data writeToFile:@"/Users/chenyanxiang/Desktop/snap.png" atomically:YES];
}
}];
獲取導(dǎo)航路線信息
// 根據(jù)兩個(gè)地標(biāo)卷谈,向蘋果服務(wù)器請(qǐng)求對(duì)應(yīng)的行走路線信息
- (void)directionsWithBeginPlackmark:(CLPlacemark *)beginP andEndPlacemark:(CLPlacemark *)endP
{
// 創(chuàng)建請(qǐng)求
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
// 設(shè)置開(kāi)始地標(biāo)
MKPlacemark *beginMP = [[MKPlacemark alloc] initWithPlacemark:beginP];
request.source = [[MKMapItem alloc] initWithPlacemark:beginMP];
// 設(shè)置結(jié)束地標(biāo)
MKPlacemark *endMP = [[MKPlacemark alloc] initWithPlacemark:endP];
request.destination = [[MKMapItem alloc] initWithPlacemark:endMP];
// 根據(jù)請(qǐng)求杯拐,獲取實(shí)際路線信息
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {
/**
MKDirectionsResponse對(duì)象解析
source :開(kāi)始位置
destination :結(jié)束位置
routes : 路線信息 (MKRoute對(duì)象)
MKRoute對(duì)象解析
name : 路的名稱
advisoryNotices : 注意警告信息
distance : 路線長(zhǎng)度(實(shí)際物理距離,單位是m)
polyline : 路線對(duì)應(yīng)的在地圖上的幾何線路(由很多點(diǎn)組成世蔗,可繪制在地圖上)
steps : 多個(gè)行走步驟組成的數(shù)組(例如“前方路口左轉(zhuǎn)”端逼,“保持直行”等等, MKRouteStep 對(duì)象)
MKRouteStep對(duì)象解析
instructions : 步驟說(shuō)明(例如“前方路口左轉(zhuǎn)”污淋,“保持直行”等等)
transportType : 通過(guò)方式(駕車顶滩,步行等)
polyline : 路線對(duì)應(yīng)的在地圖上的幾何線路(由很多點(diǎn)組成,可繪制在地圖上)
注意:
MKRoute是一整條長(zhǎng)路芙沥;MKRouteStep是這條長(zhǎng)路中的每一截诲祸;
*/
[response.routes enumerateObjectsUsingBlock:^(MKRoute * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%@--", obj.name);
[obj.steps enumerateObjectsUsingBlock:^(MKRouteStep * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%@", obj.instructions);
}];
}];
}];
}
繪制導(dǎo)航路線
路線也是一個(gè)覆蓋層
理論指導(dǎo):在地圖上操作覆蓋層,其實(shí)就是操作覆蓋層的數(shù)據(jù)模型
添加覆蓋層:在地圖上添加覆蓋層數(shù)據(jù)模型
-
刪除覆蓋層:在地圖上移除覆蓋層數(shù)據(jù)模型
-
1.創(chuàng)建路線覆蓋層模型而昨,并添加到地圖上
// 繪制線路 - (void)drawMapLine:(id <MKOverlay>)overlay { /** 注意:這里不像添加大頭針那樣救氯,只要我們添加了大頭針模型,默認(rèn)就會(huì)在地圖上添加系統(tǒng)的大頭針視圖 添加覆蓋層歌憨,需要我們實(shí)現(xiàn)對(duì)應(yīng)的代理方法着憨,在代理方法中返回對(duì)應(yīng)的覆蓋層 */ [self.mapView addOverlay:overlay]; /** 補(bǔ)充測(cè)試:添加一個(gè)圓形覆蓋層 */ // MKCircle *circle = [MKCircle circleWithCenterCoordinate:self.mapView.centerCoordinate radius:1000000]; // [self.mapView addOverlay:circle]; }
-
2.利用地圖的代理方法,返回對(duì)應(yīng)的圖層渲染
-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{ // 創(chuàng)建折線渲染對(duì)象 if ([overlay isKindOfClass:[MKPolyline class]]) { MKPolylineRenderer *lineRenderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay]; // 設(shè)置線寬 lineRenderer.lineWidth = 6; // 設(shè)置線顏色 lineRenderer.strokeColor = [UIColor redColor]; return lineRenderer; } // 創(chuàng)建圓形區(qū)域渲染對(duì)象 // if ([overlay isKindOfClass:[MKCircle class]]) { // MKCircleRenderer *circleRender = [[MKCircleRenderer alloc] initWithOverlay:overlay]; // circleRender.fillColor = [UIColor cyanColor]; // circleRender.alpha = 0.6; // return circleRender; // } return nil; }
-