一、簡介:

Mapbox致力於打造全球最漂亮的個性化地圖。
在一次偶然的地圖相關資料搜索過程中發現了一個很神奇又很漂亮的地圖,這個地圖支持高度自定義各種地圖元素,比如,道路,水系,綠地,建築物,背景色,等等。Mapbox打造的Mapbox studio地圖制作虛擬工作室,就是一個很完美的地圖元素個性化編輯器。另外,我們也可以把自己項目的地理信息數據上傳到Mapbox雲端,然后在自己項目的客戶端展現出來。
Mapbox地圖數據來源於Open Street Map(OSM)等其他地圖數據供應商,和Google Map、Apple Map等地圖廠商的地圖數據來源差不多。
二、使用:
1、注冊賬號:
在
https://www.mapbox.com 網址找到 sign up 注冊一個開發者賬號。

進入個人中心后,我們能看到 Integrate Mapbox 字樣,我們點進去,然后根據網頁的引導,我們最終會得到一個
和我們的項目相關的 Access tokens ,這個 tokens 就是我們訪問SDK的唯一key,


選擇SDK平台,這里我們選擇iOS

然后選擇 Cocoapod 安裝方式:

再接下來我們就能看到 Access tokens 了:

2、引入工程:
這里我們使用下載好的 Mapbox.framework 做示例,當然使用 cocoa pod 也行。
- 把Mapbox.frameworks 文件拖拽到 “ 項目 -> TARGETS -> Build Phases -> Embed Frameworks ” 這個路徑下;
- 在路徑 “項目 -> TARGETS -> Build Phases -> + -> New Run Script phase” 粘貼一串 shel l腳本代碼 :
bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Mapbox.framework/strip-frameworks.sh"

接下來把我們的 Access tokens 填寫到項目工程的 Info.plist 文件中:
- 在Info.plist 文件中添加 key 為 MGLMapboxAccessToken 其值為【Access tokens】 字符串;
- 在Info.plist 文件中添加 key 為 NSLocationWhenInUseUsageDescription 其值為 bool 類型的 YES;

3、Mapbox.framework類的使用:
【1】加載地圖:
-
-
-
-
@interface LoadMapboxViewController ()<MGLMapViewDelegate>
-
-
@property (nonatomic, strong) MGLMapView *mapView;
-
-
@end
-
-
@implementation LoadMapboxViewController
-
-
- ( void)viewDidLoad {
-
[ super viewDidLoad];
-
// Do any additional setup after loading the view.
-
-
self.title = @"加載地圖";
-
-
[ self.view addSubview:self.mapView];
-
}
-
-
- (MGLMapView *)mapView {
-
if (_mapView == nil) {
-
//設置地圖的 frame 和 地圖個性化樣式
-
_mapView = [[MGLMapView alloc] initWithFrame: self.view.bounds styleURL:[NSURL URLWithString:@"mapbox://styles/mapbox/streets-v10"]];
-
_mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-
//設置地圖默認顯示的地點和縮放等級
-
[_mapView setCenterCoordinate: CLLocationCoordinate2DMake(39.980528, 116.306745) zoomLevel:15 animated:YES];
-
//顯示用戶位置
-
_mapView.showsUserLocation = YES;
-
//定位模式
-
_mapView.userTrackingMode = MGLUserTrackingModeFollow;
-
//是否傾斜地圖
-
_mapView.pitchEnabled = YES;
-
//是否旋轉地圖
-
_mapView.rotateEnabled = NO;
-
//代理
-
_mapView.delegate = self;
-
}
-
return _mapView;
-
}
-
-
@end

【2】加載各種樣式的地圖:
我們可以通過如下代碼修改地圖樣式:
[self.mapView setStyleURL:[NSURL URLWithString:@"mapbox://styles/mapbox/streets-v10"]];
這是所有地圖已經做好的模板樣式參數:
- mapbox://styles/mapbox/streets-v10
- mapbox://styles/mapbox/outdoors-v10
- mapbox://styles/mapbox/light-v9
- mapbox://styles/mapbox/dark-v9
- mapbox://styles/mapbox/satellite-v9
- mapbox://styles/mapbox/satellite-streets-v10
- mapbox://styles/mapbox/navigation-preview-day-v2
- mapbox://styles/mapbox/navigation-preview-night-v2
- mapbox://styles/mapbox/navigation-guidance-day-v2
- mapbox://styles/mapbox/navigation-guidance-night-v2

【3】加載大頭針和默認氣泡:
-
//
-
// DefaultAnnotationCalloutViewController.m
-
// MapboxExample
-
//
-
// Created by iron on 2018/1/30.
-
// Copyright © 2018年 wangzhengang. All rights reserved.
-
//
-
-
-
-
-
@interface DefaultAnnotationCalloutViewController ()<MGLMapViewDelegate>
-
@property (nonatomic, strong) MGLMapView *mapView;
-
@property (nonatomic, copy) NSArray *annotationsArray;
-
@end
-
-
@implementation DefaultAnnotationCalloutViewController
-
-
- ( void)dealloc {
-
[_mapView removeFromSuperview];
-
_mapView.delegate = nil;
-
_mapView = nil;
-
}
-
-
- ( void)viewDidLoad {
-
[ super viewDidLoad];
-
-
[ self.view addSubview:self.mapView];
-
}
-
-
- ( void)didReceiveMemoryWarning {
-
[ super didReceiveMemoryWarning];
-
// Dispose of any resources that can be recreated.
-
}
-
-
-
- (MGLMapView *)mapView {
-
if (_mapView == nil) {
-
//設置地圖的 frame 和 地圖個性化樣式
-
_mapView = [[MGLMapView alloc] initWithFrame: self.view.bounds styleURL:[NSURL URLWithString:@"mapbox://styles/mapbox/streets-v10"]];
-
_mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-
//設置地圖默認顯示的地點和縮放等級
-
[_mapView setCenterCoordinate: CLLocationCoordinate2DMake(39.980528, 116.306745) zoomLevel:15 animated:NO];
-
//顯示用戶位置
-
_mapView.showsUserLocation = YES;
-
//定位模式
-
_mapView.userTrackingMode = MGLUserTrackingModeNone;
-
//是否傾斜地圖
-
_mapView.pitchEnabled = YES;
-
//是否旋轉地圖
-
_mapView.rotateEnabled = NO;
-
//代理
-
_mapView.delegate = self;
-
}
-
return _mapView;
-
}
-
-
- ( NSArray *)annotationsArray {
-
if (_annotationsArray == nil) {
-
CLLocationCoordinate2D coords[2];
-
coords[ 0] = CLLocationCoordinate2DMake(39.980528, 116.306745);
-
coords[ 1] = CLLocationCoordinate2DMake(40.000, 116.306745);
-
NSMutableArray *pointsArray = [NSMutableArray array];
-
for (NSInteger i = 0; i < 2; ++i) {
-
MGLPointAnnotation *pointAnnotation = [[MGLPointAnnotation alloc] init];
-
pointAnnotation.coordinate = coords[i];
-
pointAnnotation.title = [ NSString stringWithFormat:@"title:%ld", (long)i];
-
pointAnnotation.subtitle = [ NSString stringWithFormat:@"subtitle: %ld%ld%ld", (long)i,(long)i,(long)i];
-
[pointsArray addObject:pointAnnotation];
-
}
-
_annotationsArray = [pointsArray copy];
-
}
-
return _annotationsArray;
-
}
-
-
-
-
- ( void)mapViewDidFinishLoadingMap:(MGLMapView *)mapView {
-
///地圖加載完成時加載大頭針
-
[mapView addAnnotations: self.annotationsArray];
-
}
-
-
- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:( id<MGLAnnotation>)annotation {
-
if (![annotation isKindOfClass:[MGLPointAnnotation class]]) {
-
return nil;
-
}
-
MGLAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier: @"MGLAnnotationView"];
-
if (annotationView == nil) {
-
annotationView = [[MGLAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier: @"MGLAnnotationView"];
-
[annotationView setFrame: CGRectMake(0, 0, 40, 40)];
-
[annotationView setBackgroundColor:[ UIColor redColor]];
-
annotationView.layer.cornerRadius = 20.f;
-
annotationView.layer.masksToBounds= YES;
-
annotationView.layer.borderColor = [ UIColor whiteColor].CGColor;
-
annotationView.layer.borderWidth = 5.f;
-
}
-
return annotationView;
-
}
-
-
///是否顯示氣泡
-
-( BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id<MGLAnnotation>)annotation {
-
return YES;
-
}
-
///完成加載大頭針
-
- ( void)mapView:(MGLMapView *)mapView didAddAnnotationViews:(NSArray<MGLAnnotationView *> *)annotationViews {
-
[mapView showAnnotations: self.annotationsArray edgePadding:UIEdgeInsetsMake(100, 50, 100, 50) animated:YES];
-
}
-
-
///氣泡左側視圖
-
- ( UIView *)mapView:(MGLMapView *)mapView leftCalloutAccessoryViewForAnnotation:(id<MGLAnnotation>)annotation {
-
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
-
view.backgroundColor= [ UIColor blueColor];
-
UILabel *lab = [[UILabel alloc] initWithFrame:view.bounds];
-
lab.text = @"左側視圖";
-
lab.textColor = [ UIColor whiteColor];
-
lab.font = [ UIFont systemFontOfSize:10];
-
lab.textAlignment = NSTextAlignmentCenter;
-
[view addSubview:lab];
-
return view;
-
}
-
///氣泡右側視圖,
-
- ( UIView *)mapView:(MGLMapView *)mapView rightCalloutAccessoryViewForAnnotation:(id<MGLAnnotation>)annotation {
-
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
-
view.backgroundColor= [ UIColor greenColor];
-
UILabel *lab = [[UILabel alloc] initWithFrame:view.bounds];
-
lab.text = @"右側視圖";
-
lab.textColor = [ UIColor blackColor];
-
lab.font = [ UIFont systemFontOfSize:10];
-
[view addSubview:lab];
-
return view;
-
}
-
-
-
-
-
@end

【4】加載圖片大頭針和自定義氣泡:
- 創建一個繼承 UIview 的類 CustomeMapViewCalloutView 並遵守 < MGLCalloutView > 這個協議;
- 在 CustomeMapViewCalloutView 中實現各種需求;
- ;
實現自定義callout view:
在view controller中使用自定義的callout view:
-
//
-
// CustomeMapViewCalloutView.h
-
// Etoury
-
//
-
// Created by iron on 2017/5/21.
-
// Copyright © 2017年 iron. All rights reserved.
-
//
-
-
-
-
-
@interface CustomeMapViewCalloutView : UIView<MGLCalloutView>
-
-
-
-
@end
-
//
-
// CustomeMapViewCalloutView.m
-
// Etoury
-
//
-
// Created by iron on 2017/5/21.
-
// Copyright © 2017年 iron. All rights reserved.
-
//
-
-
-
-
// Set defaults for custom tip drawing
-
static CGFloat const tipHeight = 10.0;
-
static CGFloat const tipWidth = 20.0;
-
-
@interface CustomeMapViewCalloutView ()
-
@property (strong, nonatomic) UIButton *mainBody;
-
@end
-
-
@implementation CustomeMapViewCalloutView {
-
id <MGLAnnotation> _representedObject;
-
__unused UIView *_leftAccessoryView;/* unused */
-
__unused UIView *_rightAccessoryView;/* unused */
-
__ weak id <MGLCalloutViewDelegate> _delegate;
-
BOOL _dismissesAutomatically;
-
BOOL _anchoredToAnnotation;
-
}
-
-
@synthesize representedObject = _representedObject;
-
@synthesize leftAccessoryView = _leftAccessoryView;/* unused */
-
@synthesize rightAccessoryView = _rightAccessoryView;/* unused */
-
@synthesize delegate = _delegate;
-
@synthesize anchoredToAnnotation = _anchoredToAnnotation;
-
@synthesize dismissesAutomatically = _dismissesAutomatically;
-
-
- ( instancetype)initWithFrame:(CGRect)frame
-
{
-
self = [super initWithFrame:frame];
-
if (self)
-
{
-
self.backgroundColor = [UIColor clearColor];
-
-
// Create and add a subview to hold the callout’s text
-
UIButton *mainBody = [UIButton buttonWithType:UIButtonTypeSystem];
-
mainBody.backgroundColor = [ self backgroundColorForCallout];
-
mainBody.tintColor = [ UIColor whiteColor];
-
mainBody.contentEdgeInsets = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
-
mainBody.layer.cornerRadius = 4.0;
-
self.mainBody = mainBody;
-
-
[ self addSubview:self.mainBody];
-
}
-
-
return self;
-
}
-
-
-
-
-
- ( void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated
-
{
-
// Do not show a callout if there is no title set for the annotation
-
if (![self.representedObject respondsToSelector:@selector(title)])
-
{
-
return;
-
}
-
-
[view addSubview: self];
-
-
// Prepare title label
-
[ self.mainBody setTitle:self.representedObject.title forState:UIControlStateNormal];
-
[ self.mainBody sizeToFit];
-
-
if ([self isCalloutTappable])
-
{
-
// Handle taps and eventually try to send them to the delegate (usually the map view)
-
[ self.mainBody addTarget:self action:@selector(calloutTapped) forControlEvents:UIControlEventTouchUpInside];
-
}
-
else
-
{
-
// Disable tapping and highlighting
-
self.mainBody.userInteractionEnabled = NO;
-
}
-
-
// Prepare our frame, adding extra space at the bottom for the tip
-
CGFloat frameWidth = self.mainBody.bounds.size.width;
-
CGFloat frameHeight = self.mainBody.bounds.size.height + tipHeight;
-
CGFloat frameOriginX = rect.origin.x + (rect.size.width/2.0) - (frameWidth/2.0);
-
CGFloat frameOriginY = rect.origin.y - frameHeight;
-
self.frame = CGRectMake(frameOriginX, frameOriginY,
-
frameWidth, frameHeight);
-
-
if (animated)
-
{
-
self.alpha = 0.0;
-
-
[ UIView animateWithDuration:0.2 animations:^{
-
self.alpha = 1.0;
-
}];
-
}
-
}
-
-
- ( void)dismissCalloutAnimated:(BOOL)animated
-
{
-
if (self.superview)
-
{
-
if (animated)
-
{
-
[ UIView animateWithDuration:0.2 animations:^{
-
self.alpha = 0.0;
-
} completion:^( BOOL finished) {
-
[ self removeFromSuperview];
-
}];
-
}
-
else
-
{
-
[ self removeFromSuperview];
-
}
-
}
-
}
-
-
// Allow the callout to remain open during panning.
-
- ( BOOL)dismissesAutomatically {
-
return NO;
-
}
-
-
- ( BOOL)isAnchoredToAnnotation {
-
return YES;
-
}
-
-
// https://github.com/mapbox/mapbox-gl-native/issues/9228
-
- ( void)setCenter:(CGPoint)center {
-
center.y = center.y - CGRectGetMidY(self.bounds);
-
[ super setCenter:center];
-
}
-
-
-
-
- ( BOOL)isCalloutTappable
-
{
-
if ([self.delegate respondsToSelector:@selector(calloutViewShouldHighlight:)]) {
-
return [self.delegate performSelector:@selector(calloutViewShouldHighlight:) withObject:self];
-
}
-
-
return NO;
-
}
-
-
- ( void)calloutTapped
-
{
-
if ([self isCalloutTappable] && [self.delegate respondsToSelector:@selector(calloutViewTapped:)])
-
{
-
[ self.delegate performSelector:@selector(calloutViewTapped:) withObject:self];
-
}
-
}
-
-
-
-
- ( UIColor *)backgroundColorForCallout
-
{
-
return [UIColor darkGrayColor];
-
}
-
-
- ( void)drawRect:(CGRect)rect
-
{
-
// Draw the pointed tip at the bottom
-
UIColor *fillColor = [self backgroundColorForCallout];
-
-
CGFloat tipLeft = rect.origin.x + (rect.size.width / 2.0) - (tipWidth / 2.0);
-
CGPoint tipBottom = CGPointMake(rect.origin.x + (rect.size.width / 2.0), rect.origin.y + rect.size.height);
-
CGFloat heightWithoutTip = rect.size.height - tipHeight - 1;
-
-
CGContextRef currentContext = UIGraphicsGetCurrentContext();
-
-
CGMutablePathRef tipPath = CGPathCreateMutable();
-
CGPathMoveToPoint(tipPath, NULL, tipLeft, heightWithoutTip);
-
CGPathAddLineToPoint(tipPath, NULL, tipBottom.x, tipBottom.y);
-
CGPathAddLineToPoint(tipPath, NULL, tipLeft + tipWidth, heightWithoutTip);
-
CGPathCloseSubpath(tipPath);
-
-
[fillColor setFill];
-
CGContextAddPath(currentContext, tipPath);
-
CGContextFillPath(currentContext);
-
CGPathRelease(tipPath);
-
}
-
-
-
-
-
-
@end
在view controller中使用自定義的callout view:
-
//
-
// CustomeAnnotationCalloutViewController.m
-
// MapboxExample
-
//
-
// Created by iron on 2018/1/30.
-
// Copyright © 2018年 wangzhengang. All rights reserved.
-
//
-
-
-
-
-
-
@interface CustomeAnnotationCalloutViewController ()<MGLMapViewDelegate>
-
@property (nonatomic, strong) MGLMapView *mapView;
-
@property (nonatomic, copy) NSArray *annotationsArray;
-
-
@end
-
-
@implementation CustomeAnnotationCalloutViewController
-
-
-
- ( void)dealloc {
-
[_mapView removeFromSuperview];
-
_mapView.delegate = nil;
-
_mapView = nil;
-
}
-
-
-
- ( void)viewDidLoad {
-
[ super viewDidLoad];
-
-
[ self.view addSubview:self.mapView];
-
}
-
-
-
- (MGLMapView *)mapView {
-
if (_mapView == nil) {
-
//設置地圖的 frame 和 地圖個性化樣式
-
_mapView = [[MGLMapView alloc] initWithFrame: self.view.bounds styleURL:[NSURL URLWithString:@"mapbox://styles/mapbox/streets-v10"]];
-
_mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-
//設置地圖默認顯示的地點和縮放等級
-
[_mapView setCenterCoordinate: CLLocationCoordinate2DMake(39.980528, 116.306745) zoomLevel:15 animated:NO];
-
//顯示用戶位置
-
_mapView.showsUserLocation = YES;
-
//定位模式
-
_mapView.userTrackingMode = MGLUserTrackingModeNone;
-
//是否傾斜地圖
-
_mapView.pitchEnabled = YES;
-
//是否旋轉地圖
-
_mapView.rotateEnabled = NO;
-
//代理
-
_mapView.delegate = self;
-
}
-
return _mapView;
-
}
-
-
- ( NSArray *)annotationsArray {
-
if (_annotationsArray == nil) {
-
CLLocationCoordinate2D coords[2];
-
coords[ 0] = CLLocationCoordinate2DMake(39.980528, 116.306745);
-
coords[ 1] = CLLocationCoordinate2DMake(40.000, 116.306745);
-
NSMutableArray *pointsArray = [NSMutableArray array];
-
for (NSInteger i = 0; i < 2; ++i) {
-
MGLPointAnnotation *pointAnnotation = [[MGLPointAnnotation alloc] init];
-
pointAnnotation.coordinate = coords[i];
-
pointAnnotation.title = [ NSString stringWithFormat:@"title:%ld", (long)i];
-
pointAnnotation.subtitle = [ NSString stringWithFormat:@"subtitle: %ld%ld%ld", (long)i,(long)i,(long)i];
-
[pointsArray addObject:pointAnnotation];
-
}
-
_annotationsArray = [pointsArray copy];
-
}
-
return _annotationsArray;
-
}
-
-
-
-
- ( void)mapViewDidFinishLoadingMap:(MGLMapView *)mapView {
-
///地圖加載完成時加載大頭針
-
[mapView addAnnotations: self.annotationsArray];
-
}
-
-
- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:( id<MGLAnnotation>)annotation {
-
if (![annotation isKindOfClass:[MGLPointAnnotation class]]) {
-
return nil;
-
}
-
MGLAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier: @"MGLAnnotationView"];
-
if (annotationView == nil) {
-
annotationView = [[MGLAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier: @"MGLAnnotationView"];
-
[annotationView setFrame: CGRectMake(0, 0, 40, 40)];
-
[annotationView setBackgroundColor:[ UIColor redColor]];
-
annotationView.layer.cornerRadius = 20.f;
-
annotationView.layer.masksToBounds= YES;
-
annotationView.layer.borderColor = [ UIColor whiteColor].CGColor;
-
annotationView.layer.borderWidth = 5.f;
-
}
-
return annotationView;
-
}
-
-
///是否顯示氣泡
-
-( BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id<MGLAnnotation>)annotation {
-
return YES;
-
}
-
///完成加載大頭針
-
- ( void)mapView:(MGLMapView *)mapView didAddAnnotationViews:(NSArray<MGLAnnotationView *> *)annotationViews {
-
[mapView showAnnotations: self.annotationsArray edgePadding:UIEdgeInsetsMake(100, 50, 100, 50) animated:YES];
-
}
-
-
///加載定義callout view
-
- ( id<MGLCalloutView>)mapView:(MGLMapView *)mapView calloutViewForAnnotation:(id<MGLAnnotation>)annotation {
-
CustomeMapViewCalloutView *calloutView = [[CustomeMapViewCalloutView alloc] init];
-
calloutView.representedObject = annotation;
-
return calloutView;
-
}
-
-
///氣泡點擊事件
-
- ( void)mapView:(MGLMapView *)mapView tapOnCalloutForAnnotation:(id<MGLAnnotation>)annotation {
-
NSLog(@"點擊了氣泡: %@", annotation);
-
[mapView deselectAnnotation:annotation animated: YES];
-
-
[ self showAlertControllerWithViewContorller:self title:@"點擊了氣泡" message:nil leftButtonTitle:nil rightButtonTitle:@"確定"];
-
}
-
-
-
-
- ( void)showAlertControllerWithViewContorller:(UIViewController *)viewController title:(NSString *)title message:(NSString *)message leftButtonTitle:(NSString *)leftBtnTitle rightButtonTitle:(NSString *)rightBtnTitle {
-
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
-
if (leftBtnTitle) {
-
[alert addAction:[ UIAlertAction actionWithTitle:leftBtnTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
-
-
}]];
-
}
-
if (rightBtnTitle) {
-
[alert addAction:[ UIAlertAction actionWithTitle:rightBtnTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
-
-
}]];
-
}
-
[viewController presentViewController:alert animated: YES completion:nil];
-
}
-
-
-
@end


【5】繪制線段和多邊形:
老實說 Mapbox 的 繪制線段和多邊形的相關類,相比高德地圖和百度地圖寫的並不好,用起來很不方便,比如:
- MGLPolygon 有 strokeColor 這個參數,卻沒有設置 描邊線寬度和樣式的參數;
- MGLPolyline 沒有 strokeColor 和 fillColor 之分,而且畫虛線的代碼寫起來很麻煩;
為了提高 MGLPolygon 和 MGLPolyline 的使用便利性,我對 MGLPolygon 、MGLPolyline 的基類 MGLShape 擴展了幾個屬性:
- @property (nonatomic, strong) UIColor *fillColor;//填充顏色
- @property (nonatomic, assign) CGFloat fillOpacity;//填充透明度
- @property (nonatomic, strong) UIColor *strokeColor;//描邊顏色
- @property (nonatomic, assign) BOOL isDash;//YES = 虛線/NO = 實線
- @property (nonatomic, assign) NSInteger strokeWeight;//描邊寬度
接下來讓我們看看整體代碼是如何實現的,以及最后的效果是怎樣的:
MGLShape+PolygonParamer.h
-
//
-
// MGLShape+PolygonParamer.h
-
// Etoury
-
//
-
// Created by dev on 2018/1/3.
-
// Copyright © 2018年 iron. All rights reserved.
-
//
-
-
-
-
@interface MGLShape (PolygonParamer)
-
-
-
-
@property (nonatomic, strong) UIColor *fillColor;//填充顏色
-
@property (nonatomic, assign) CGFloat fillOpacity;//填充透明度
-
@property (nonatomic, strong) UIColor *strokeColor;//描邊顏色
-
@property (nonatomic, assign) BOOL isDash;//YES = 虛線/NO = 實線
-
@property (nonatomic, assign) NSInteger strokeWeight;//描邊寬度
-
-
-
-
-
@end
MGLShape+PolygonParamer.h
-
//
-
// MGLShape+PolygonParamer.m
-
// Etoury
-
//
-
// Created by dev on 2018/1/3.
-
// Copyright © 2018年 iron. All rights reserved.
-
//
-
-
-
-
-
-
static UIColor *_fillColor;//填充顏色
-
static NSInteger _fillOpacity;//填充透明度
-
static UIColor *_strokeColor;//描邊顏色
-
static BOOL _isDash;//YES = 虛線/NO = 實線
-
static NSInteger _strokeWeight;//描邊寬度
-
-
-
-
@implementation MGLShape (PolygonParamer)
-
-
-
- ( void)setFillColor:(UIColor *)fillColor {
-
objc_setAssociatedObject( self, &_fillColor, fillColor, OBJC_ASSOCIATION_COPY);
-
}
-
- ( UIColor *)fillColor {
-
return objc_getAssociatedObject(self, &_fillColor);
-
}
-
-
-
- ( void)setFillOpacity:(CGFloat)fillOpacity {
-
NSNumber *fillOpacityNumber = @(fillOpacity);
-
objc_setAssociatedObject( self, &_fillOpacity, fillOpacityNumber, OBJC_ASSOCIATION_COPY);
-
}
-
- ( CGFloat)fillOpacity {
-
NSNumber *fillOpacityNumber = objc_getAssociatedObject(self, &_fillOpacity);
-
return [fillOpacityNumber floatValue];
-
}
-
-
-
- ( void)setStrokeColor:(UIColor *)strokeColor {
-
objc_setAssociatedObject( self, &_strokeColor, strokeColor, OBJC_ASSOCIATION_COPY);
-
}
-
- ( UIColor *)strokeColor {
-
return objc_getAssociatedObject(self, &_strokeColor);
-
}
-
-
-
- ( void)setIsDash:(BOOL)isDash {
-
NSNumber *isDashNumber = [NSNumber numberWithBool:isDash];
-
objc_setAssociatedObject( self, &_isDash, isDashNumber, OBJC_ASSOCIATION_COPY);
-
}
-
- ( BOOL)isDash {
-
NSNumber *isDashNumber = objc_getAssociatedObject(self, &_isDash);
-
return [isDashNumber boolValue];
-
}
-
-
-
- ( void)setStrokeWeight:(NSInteger)strokeWeight {
-
NSNumber *strokeWeightNumber = @(strokeWeight);
-
objc_setAssociatedObject( self, &_strokeWeight, strokeWeightNumber, OBJC_ASSOCIATION_COPY);
-
}
-
- ( NSInteger)strokeWeight {
-
NSNumber *strokeWeightNumber = objc_getAssociatedObject(self, &_strokeWeight);
-
return [strokeWeightNumber integerValue];
-
}
-
-
-
-
-
@end
把 MGLShape+PolygonParamer引入到 view controller 中:
-
//
-
// LinePolygonMapboxViewController.m
-
// MapboxExample
-
//
-
// Created by iron on 2018/1/30.
-
// Copyright © 2018年 wangzhengang. All rights reserved.
-
//
-
-
-
-
-
-
-
@interface LinePolygonMapboxViewController ()<MGLMapViewDelegate>
-
@property (nonatomic, strong) MGLMapView *mapView;
-
-
@property (nonatomic, strong) MGLPolyline *blueLine;//藍色線段
-
-
@property (nonatomic, strong) MGLPolyline *strokeLine;//多邊形邊線
-
@property (nonatomic, strong) MGLPolygon *polygon;//多邊形
-
-
@end
-
-
@implementation LinePolygonMapboxViewController
-
-
- ( void)dealloc {
-
[_mapView removeFromSuperview];
-
_mapView.delegate = nil;
-
_mapView = nil;
-
}
-
-
- ( void)viewDidLoad {
-
[ super viewDidLoad];
-
-
self.title = @"線段和多邊形";
-
-
[ self.view addSubview:self.mapView];
-
}
-
-
- ( void)didReceiveMemoryWarning {
-
[ super didReceiveMemoryWarning];
-
// Dispose of any resources that can be recreated.
-
}
-
-
- (MGLMapView *)mapView {
-
if (_mapView == nil) {
-
//設置地圖的 frame 和 地圖個性化樣式
-
_mapView = [[MGLMapView alloc] initWithFrame: self.view.bounds styleURL:[NSURL URLWithString:@"mapbox://styles/mapbox/streets-v10"]];
-
_mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-
//設置地圖默認顯示的地點和縮放等級
-
[_mapView setCenterCoordinate: CLLocationCoordinate2DMake(39.980528, 116.306745) zoomLevel:8 animated:YES];
-
//顯示用戶位置
-
_mapView.showsUserLocation = YES;
-
//定位模式
-
_mapView.userTrackingMode = MGLUserTrackingModeNone;
-
//是否傾斜地圖
-
_mapView.pitchEnabled = YES;
-
//是否旋轉地圖
-
_mapView.rotateEnabled = NO;
-
//代理
-
_mapView.delegate = self;
-
}
-
return _mapView;
-
}
-
-
-
- (MGLPolyline *)blueLine {
-
if (_blueLine == nil) {
-
CLLocationCoordinate2D coords[3];
-
coords[ 0] = CLLocationCoordinate2DMake(27.000, 95.356745);
-
coords[ 1] = CLLocationCoordinate2DMake(20.000, 105.356745);
-
coords[ 2] = CLLocationCoordinate2DMake(27.000, 115.356745);
-
-
_blueLine = [MGLPolyline polylineWithCoordinates:coords count: 3];
-
_blueLine.strokeColor = [ UIColor blueColor];
-
_blueLine.strokeWeight = 3.f;
-
_blueLine.fillOpacity = 0.75f;
-
_blueLine.isDash = NO;
-
}
-
return _blueLine;
-
}
-
-
- (MGLPolyline *)strokeLine {
-
if (_strokeLine == nil) {
-
CLLocationCoordinate2D coords[6];
-
coords[ 0] = CLLocationCoordinate2DMake(30.980528, 110.306745);
-
coords[ 2] = CLLocationCoordinate2DMake(30.000, 120.306745);
-
coords[ 1] = CLLocationCoordinate2DMake(40.000, 120.306745);
-
coords[ 3] = CLLocationCoordinate2DMake(40.000, 110.306745);
-
coords[ 4] = CLLocationCoordinate2DMake(35.000, 95.356745);
-
coords[ 5] = CLLocationCoordinate2DMake(30.980528, 110.306745);;
-
_strokeLine = [MGLPolyline polylineWithCoordinates:coords count: 6];
-
_strokeLine.strokeColor = [ UIColor blackColor];
-
_strokeLine.strokeWeight = 2.f;
-
_strokeLine.fillOpacity = 0.75f;
-
_strokeLine.isDash = YES;
-
}
-
return _strokeLine;
-
}
-
-
- (MGLPolygon *)polygon {
-
if (_polygon == nil) {
-
CLLocationCoordinate2D coords[6];
-
coords[ 0] = CLLocationCoordinate2DMake(30.980528, 110.306745);
-
coords[ 2] = CLLocationCoordinate2DMake(30.000, 120.306745);
-
coords[ 1] = CLLocationCoordinate2DMake(40.000, 120.306745);
-
coords[ 3] = CLLocationCoordinate2DMake(40.000, 110.306745);
-
coords[ 4] = CLLocationCoordinate2DMake(35.000, 95.356745);
-
_polygon = [MGLPolygon polygonWithCoordinates:coords count: 5];
-
_polygon.fillColor = [ UIColor redColor];
-
_polygon.strokeColor = [ UIColor blueColor];
-
_polygon.strokeWeight= 2.f;
-
_polygon.fillOpacity = 0.5f;
-
}
-
return _polygon;
-
}
-
-
-
- ( void)mapViewDidFinishLoadingMap:(MGLMapView *)mapView {
-
///地圖加載完成后繪制 線段 和 多邊形
-
[mapView addOverlays:@[ self.blueLine, self.strokeLine, self.polygon]];
-
///把窗口顯示到合適的范圍
-
[mapView setVisibleCoordinateBounds: self.polygon.overlayBounds edgePadding:UIEdgeInsetsMake(0, 10, 200, 10) animated:YES];
-
-
// [mapView setVisibleCoordinateBounds:self.line.overlayBounds edgePadding:UIEdgeInsetsMake(300, 10, 0, 10) animated:YES];
-
}
-
-
- ( CGFloat)mapView:(MGLMapView *)mapView alphaForShapeAnnotation:(MGLShape *)annotation {
-
///MGLPolyline 和 MGLPolygon 都執行這個方法
-
return annotation.fillOpacity;
-
}
-
-
- ( UIColor *)mapView:(MGLMapView *)mapView strokeColorForShapeAnnotation:(MGLShape *)annotation {
-
///MGLPolyline 和 MGLPolygon 都執行這個方法
-
if ([@"MGLPolyline" isEqualToString:NSStringFromClass([annotation class])]) {
-
-
if (annotation.isDash) {
-
MGLShapeSource *shapeSource = [ self addSourceWithShape:annotation];
-
[ self.mapView.style addSource:shapeSource];
-
MGLStyleLayer *styleLayer = [ self dashedLineWithStyle:shapeSource shape:annotation lineDashPattern:@[@2.f, @1.f] lineCap:MGLLineCapButt lineColor:[UIColor blackColor] lineWidth:@2];
-
[ self.mapView.style addLayer:styleLayer];
-
return [UIColor clearColor];
-
} else {
-
return annotation.strokeColor;
-
}
-
} else if ([@"MGLPolygon" isEqualToString:NSStringFromClass([annotation class])]) {
-
-
return annotation.strokeColor;
-
}
-
return annotation.strokeColor;
-
}
-
-
- ( UIColor *)mapView:(MGLMapView *)mapView fillColorForPolygonAnnotation:(MGLPolygon *)annotation {
-
/// MGLPolygon 執行這個方法, MGLPolyline 不執行這個方法
-
return annotation.fillColor;
-
}
-
-
- ( CGFloat)mapView:(MGLMapView *)mapView lineWidthForPolylineAnnotation:(MGLPolyline *)annotation {
-
///MGLPolyline 執行這個方法, MGLPolygon 不執行
-
return annotation.strokeWeight;
-
}
-
-
-
- (MGLShapeSource *)addSourceWithShape:(MGLShape *)shape {
-
return [[MGLShapeSource alloc] initWithIdentifier:@"DashLines" shape:shape options:nil];
-
}
-
-
- (MGLStyleLayer *)dashedLineWithStyle:(MGLShapeSource *)shapeSource shape:(MGLShape *)shape lineDashPattern:( NSArray<NSNumber *> *)lineDashPattern lineCap:(MGLLineCap)cap lineColor:(UIColor *)lineColor lineWidth:(NSNumber *)lineWidth {
-
MGLLineStyleLayer *lineStyleLayer = [[MGLLineStyleLayer alloc] initWithIdentifier: @"DashLines" source:shapeSource];
-
//線段模型
-
lineStyleLayer.lineDashPattern = [MGLStyleValue valueWithRawValue:lineDashPattern];
-
//線段頭部
-
lineStyleLayer.lineCap = [MGLStyleValue valueWithRawValue:[ NSNumber numberWithInteger:cap]];
-
//線段顏色
-
lineStyleLayer.lineColor = [MGLStyleValue valueWithRawValue:lineColor];
-
//線段寬度
-
lineStyleLayer.lineWidth = [MGLStyleValue valueWithRawValue:lineWidth];
-
return lineStyleLayer;
-
}
-
-
-
-
-
-
@end
- 實現 MGLShape (PolygonParamer) 擴展類 MGLShape+PolygonParamer ;
- 把 MGLShape+PolygonParamer.h 引入到 LinePolygonMapboxViewController.h 這個 view controller 中;
- 運行看效果;
現在文章到這里只是講述了 Mapbox 的常規使用,后續我會更新關於 多點聚合、位置方向等的使用。。。
項目示例代碼在GitHub上的地址:
https://github.com/wangzhengang/MapboxExample/
如果您覺得對您有用,請在GitHub上給個星星。