iOS -- 地图画圈

原文链接:http://lipengxuan.easymorse.com/?p=588              http://lipengxuan.easymorse.com/?p=598

iOS上地图画线,画线区域内的经纬度坐标点添加大头针



实现在Google地图上用手指可以画线的功能,同时地图上的一点(经纬度坐标点)如果在画线的区域内,会在这个点落下大头针的功能,类似大众点评的画线圈商铺的效果

在做了前两篇博客的工作以后,对手指移动画线的方法有了了解,所以思路是一样的,先在根视图上加一个MapView,然后在MapView上面加画图的View,也就是说地图是地图,画线是画线,互不干扰,但是这样做的话怎么能实现范围内经纬度点的识别呢?这里就要用到地图坐标和画图坐标的转换,后面会讲。

所以解决方法是在画布View上画图,然后通过坐标转换获得这一圈儿的经纬度坐标点,然后在经纬度值的范围内的坐标点找出来,然后在这个坐标点上加大头针。

但是在实际操作中发现就算我获得了这一圈儿的经纬度值,存在一个数组里,我也不知道如何判断某个经纬度是不是在这个范围之内。

所以反着来想,之前的解决思路是View上的坐标转化成地图的经纬度坐标,当然也可以把地图上经纬度坐标转化成View上的坐标,因为在View上CGPath范围内的点是可以找出来的(后面会讲),所以后来决定按这个思路做,会更顺利些。

 

 

下面是具体代码,首先创建一个SingleView项目,引入必要的两个库文件CoreLocation.framewrok和MapKit.framework,地图的展示和定位都要用到,然后ViewController.h头文件添加如下代码:

#import <UIKit/UIKit.h>

#import “MapKit/MapKit.h”

@interface ViewController : UIViewController<CLLocationManagerDelegate,MKMapViewDelegate>

{

MKMapView *innerMap;//地图层

UIImageView *imageView;//绘画层

CLLocationManager *locationManager;//定位实例

NSMutableArray *array;//存储经纬度坐标的数组,这里用不着

CGMutablePathRef pathRef;//手指画线的Path

CLLocationCoordinate2D testLocation;//测试的位置(经纬度)

CGPoint locationConverToImage;//存储转换测试位置的CGPoint

}

@end

之后是终点ViewController.m的代码,视图中两个按钮就不说了,通过IB拖拽的,功能函数下面会说,功能如其名,首先是ViewDidLoad方法:

- (void)viewDidLoad

{

[super viewDidLoad];

//添加地图层

innerMap=[[MKMapView alloc] initWithFrame:CGRectMake(0, 50, 320, 430)];

[self.view addSubview:innerMap];

//[innerMap setShowsUserLocation:YES];//不显示定位小蓝点儿

[innerMap setDelegate:self];

//添加定位信息,为了设置地图显示的Region范围

locationManager = [[CLLocationManager alloc] init];

locationManager.delegate=self;

locationManager.desiredAccuracy=kCLLocationAccuracyBest;

locationManager.distanceFilter=1000.0f;

[locationManager startUpdatingLocation];

MKCoordinateSpan theSpan;

theSpan.latitudeDelta=0.03;

theSpan.longitudeDelta=0.03;

MKCoordinateRegion theRegion={ {0.0, 0.0 }, { 0.0, 0.0 } };

theRegion.center=locationManager.location.coordinate;

theRegion.span=theSpan;

[innerMap setRegion:theRegion animated:YES];

//用当前经纬度来设置测试经纬度点,便于查看

// NSLog(@”latitude !!! %f”,locationManager.location.coordinate.latitude);

//  NSLog(@”longtitude !!! %f”,locationManager.location.coordinate.longitude);

//初始化数组为以后存储数据使用

array=[NSMutableArray array];

}

 上面的代码加载了按钮和地图,并让地图显示区域调整到当前位置为中心的一个范围内,准备工作做好了,下面是draw按钮的代码,事件如下:

-(IBAction)drawFunction:(id)sender{

imageView=[[UIImageView alloc] initWithFrame:innerMap.frame];

[self.view addSubview:imageView];

imageView.userInteractionEnabled=YES;

UIGraphicsBeginImageContext(imageView.frame.size);

[imageView.image drawInRect:CGRectMake(0, 0, imageView.frame.size.width, imageView.frame.size.height)];

CGContextSetRGBFillColor(UIGraphicsGetCurrentContext(), 50, 79, 133, 1.0);

CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor redColor].CGColor);

CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 4);

//地理坐标转换成点

testLocation.latitude=39.995012;//设定测试点的坐标是当前位置

testLocation.longitude=116.411892;

locationConverToImage=[innerMap convertCoordinate:testLocation toPointToView:imageView];

// NSLog(@”111 %f”,locationConverToImage.x);

// NSLog(@”222 %f”,locationConverToImage.y);

}

上面的方法点击后会创建一个imageView,我们会在上面来画图,同时设定了上下文和画线的宽度填充色等元素,最底下
convertCoordinate:toPointToView:
这个方法就是坐标转换的方法了,把一个经纬度坐标转化为CGPoint坐标并存储在locationConverToImage里,这里要说明一下坐标的转化了,坐标转化能做什么呢?
(1)让当前屏幕显示区域的CGPoint点坐标(x,y)值映射到当前地图可视区域同一个位置的CLLocationCoordinate2D(latitude,longitude)值,也就是让绘图层上的一点的xy值对应地图层上一点的经纬度值
(2)反之,让地图上的经纬度点坐标转换成同位置的CGPoint点坐标。
这里我觉得这个方法的功能实现的很奇妙,两个毫不相关的层就这么互通有无了,相信苹果一定利用某种算法计算了当前显示的地图区域的缩放等级并有一个经纬度范围。
总之这个draw按钮的点击创建了绘画层,也定义了一个测试的经纬度坐标点,同时把这个点转换成了imageView上面的CGPoint点
再看下Clear按钮:

-(IBAction)clearFunction:(id)sender{

[imageView removeFromSuperview];//删除绘图层

[array removeAllObjects];

[innerMap removeAnnotations:innerMap.annotations];//删除大头针

UIGraphicsEndImageContext();//删除画布

}

这个就比较简单了,剩下的就是添加touch的三个方法,begin,move,end,在begin和move的时候画图,在end的时候做判断区域的处理并添加大头针

首先是touchbegin:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

UITouch *touch = [touches anyObject];

CGPoint location = [touch locationInView:imageView];

//创建path

pathRef=CGPathCreateMutable();

CGPathMoveToPoint(pathRef, NULL, location.x, location.y);

}

在点击开始的方法里记录了点击的坐标,同时创建了一个CGPath,并设置起点为当前坐标,这个Path在手指移动的时候会跟随着改变,接下来是touchmove方法:

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

UITouch *touch = [touches anyObject];

CGPoint location = [touch locationInView:imageView];

CGPoint pastLocation = [touch previousLocationInView:imageView];

//画线

CGContextMoveToPoint(UIGraphicsGetCurrentContext(), pastLocation.x, pastLocation.y);

CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), location.x, location.y);

CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);

imageView.image=UIGraphicsGetImageFromCurrentImageContext();

//更新Path

CGPathAddLineToPoint(pathRef, NULL, location.x, location.y);

}

这里的画线部分和之前的博客一样,值得注意的是每一次touchmove都会让path跟着更新,接下来是touchend方法:

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

CGPathCloseSubpath(pathRef);

if (CGPathContainsPoint(pathRef, NULL, locationConverToImage, NO)) {

NSLog(@”point in path!”);

MKPointAnnotation *pointAnnotation = nil;

pointAnnotation = [[MKPointAnnotation alloc] init];

pointAnnotation.coordinate = locationManager.location.coordinate;

pointAnnotation.title = @”大头针”;

[innerMap addAnnotation:pointAnnotation];

}

}

可以看到抬手的时候判断是否在path区域内的点locationConverToImage就是测试经纬度坐标点转化完以后的点,如果在这个区域里就添加大头针,如果想让大头针有落下的动画或者自定义颜色还要加上这个代理方法:

- (MKAnnotationView*) mapView: (MKMapView*) mapView viewForAnnotation: (id<MKAnnotation>) annotation{

MKPinAnnotationView *pinView = nil;

static NSString *defaultPinID = @”com.invasivecode.pin”;

pinView = (MKPinAnnotationView *)[innerMap dequeueReusableAnnotationViewWithIdentifier:defaultPinID];

if ( pinView == nil ) pinView = [[MKPinAnnotationView alloc]

initWithAnnotation:annotation reuseIdentifier:defaultPinID];

pinView.pinColor = MKPinAnnotationColorPurple;

pinView.animatesDrop = YES;

[innerMap.userLocation setTitle:@"欧陆经典"];

[innerMap.userLocation setSubtitle:@"vsp"];

return pinView;

}

接下来要完成的是填充path颜色,增加多个点等等,有待继续完善


iOS地图画线区域填充颜色的方法

之前的博客记录了如何 在google地图上面手工画线,并在画线区域内显示特定经纬度的坐标点,然后在坐标点上加大头针的情况,但是没有实现填充色,这里记录实现填充色方法:

静态画线中很容易填充path颜色,但是动态随着手指移动添加的时候总是加不上,于是决定在松手的时候重新绘制一遍path并填充颜色,也就是在touchend里面再实现一次静态画线填充颜色,那么首先就要记录画线时的坐标点,这样在touchend时可以利用这些坐标点来静态画线,在touchbegan方法里:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

UITouch *touch = [touches anyObject];

CGPoint location = [touch locationInView:imageView];

beginPoint=location;

//创建path

pathRef=CGPathCreateMutable();

CGPathMoveToPoint(pathRef, NULL, location.x, location.y);

//CoordinateClass是我自己创建的类,一个NSObject类,存储坐标点,里面有x和y成员

CoordinateClass *point1=[[CoordinateClass alloc] init];

[point1 initCoordinate:location];

[array addObject:point1];//touch起始点添加到数组

}

然后是touchmove事件记录每一个移动的点,添加如下代码:

   UITouch *touch = [touches anyObject];

CGPoint location = [touch locationInView:imageView];

CoordinateClass *point=[[CoordinateClass alloc] init];

[point initCoordinate:location];

[array addObject:point];

这样就记录了轨迹中的坐标点,存在了aray数组中,接下来主要就是touchend事件:

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

//自动闭合线路,松手时画一条松手点到起点的线

CGContextMoveToPoint(UIGraphicsGetCurrentContext(), upPoint.x, upPoint.y);

CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), beginPoint.x, beginPoint.y);

CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);

imageView.image=UIGraphicsGetImageFromCurrentImageContext();

 

CGPathAddLineToPoint(pathRef, NULL, beginPoint.x, beginPoint.y);

CGPathCloseSubpath(pathRef);

//加大头针,自己写的判断范围函数

[self addAnotationView:locationConverToImage];

[self addAnotationView:locationConverToImage2];

[self addAnotationView:locationConverToImage3];

[self addAnotationView:locationConverToImage4];

[self addAnotationView:locationConverToImage5];

[self addAnotationView:locationConverToImage6];

[self addAnotationView:locationConverToImage7];

[self addAnotationView:locationConverToImage8];

//fill代码

CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor colorWithRed:0.7 green:0.2 blue:0.6 alpha:0.23].CGColor);

CGContextBeginPath(UIGraphicsGetCurrentContext());

CGContextMoveToPoint(UIGraphicsGetCurrentContext(), beginPoint.x, beginPoint.y);

for (int i=0; i<[array count]; i++) {

[self addlineFunction:[array objectAtIndex:i]];

}

//填充和画线函数

CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);

CGContextClosePath(UIGraphicsGetCurrentContext());

imageView.image=UIGraphicsGetImageFromCurrentImageContext();

}

经验就是画线可以用

CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);

别忘了设置imageview的image。

当然还可以用

    CGContextFillPath(<#CGContextRef c#>)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值