iPhone:如何在MapKit上的两点之间画线?
我有两点的经度和纬度,并希望在MapKit上用Pin来绘制这两点之间的线。
我google了,但无法find一些合适的解决scheme,因为我发现一个数据点的数组覆盖,但我没有这两点之间的任何点数组。
只是两点,想要在这两点之间画线。
请帮忙。
首先让你的视图控制器实现MKMapViewDelegate
协议,并声明你将需要的属性:
@property (nonatomic, retain) MKMapView *mapView; //this is your map view @property (nonatomic, retain) MKPolyline *routeLine; //your line @property (nonatomic, retain) MKPolylineView *routeLineView; //overlay view
然后在viewDidLoad
(例如,或者你初始化的任何地方)
//initialize your map view and add it to your view hierarchy - **set its delegate to self*** CLLocationCoordinate2D coordinateArray[2]; coordinateArray[0] = CLLocationCoordinate2DMake(lat1, lon1); coordinateArray[1] = CLLocationCoordinate2DMake(lat2, lon2); self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2]; [self.mapView setVisibleMapRect:[self.routeLine boundingMapRect]]; //If you want the route to be visible [self.mapView addOverlay:self.routeLine];
然后实现MKMapViewDelegate
的方法-(MKOverlayView *)mapView:viewForOverlay:
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay { if(overlay == self.routeLine) { if(nil == self.routeLineView) { self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease]; self.routeLineView.fillColor = [UIColor redColor]; self.routeLineView.strokeColor = [UIColor redColor]; self.routeLineView.lineWidth = 5; } return self.routeLineView; } return nil; }
你可以调整代码以适合你的需要,但是它非常直截了当,甚至2点或更多点。
请参阅本教程在mkmapview中绘制折线或路线
1> 使用mapkit绘制路线
2>从ios4.0以上的版本您可以使用MKOverlayPathView请参阅Apple文档
示例代码: –
创buildPolyLine: –
-(void) loadRoute { NSString* filePath = [[NSBundle mainBundle] pathForResource:@”route” ofType:@”csv”]; NSString* fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; NSArray* pointStrings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; MKMapPoint northEastPoint; MKMapPoint southWestPoint; MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * pointStrings.count); for(int idx = 0; idx < pointStrings.count; idx++) { NSString* currentPointString = [pointStrings objectAtIndex:idx]; NSArray* latLonArr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@","]]; CLLocationDegrees latitude = [[latLonArr objectAtIndex:0] doubleValue]; CLLocationDegrees longitude = [[latLonArr objectAtIndex:1] doubleValue]; CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude); MKMapPoint point = MKMapPointForCoordinate(coordinate); if (idx == 0) { northEastPoint = point; southWestPoint = point; } else { if (point.x > northEastPoint.x) northEastPoint.x = point.x; if(point.y > northEastPoint.y) northEastPoint.y = point.y; if (point.x < southWestPoint.x) southWestPoint.x = point.x; if (point.y < southWestPoint.y) southWestPoint.y = point.y; } pointArr[idx] = point; } self.routeLine = [MKPolyline polylineWithPoints:pointArr count:pointStrings.count]; _routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y); free(pointArr); }
显示PoluLine: –
[self.mapView addOverlay:self.routeLine];
单独添加叠加层将不会在地图上显示任何内容。 你的MKMapViewDelegate实现必须返回一个覆盖这个你刚添加的路由,因为简单的添加不会有帮助。
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay { MKOverlayView* overlayView = nil; if(overlay == self.routeLine) { //if we have not yet created an overlay view for this overlay, create it now. if(nil == self.routeLineView) { self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease]; self.routeLineView.fillColor = [UIColor redColor]; self.routeLineView.strokeColor = [UIColor redColor]; self.routeLineView.lineWidth = 3; } overlayView = self.routeLineView; } return overlayView; }
#import <MapKit/MapKit.h> - (void)viewDidLoad { [mapview setDelegate:self]; mapview.showsUserLocation = YES; } - (CLLocationCoordinate2D)coordinateWithLocation:(NSDictionary*)location { double latitude = [[location objectForKey:@"lat"] doubleValue]; double longitude = [[location objectForKey:@"lng"] doubleValue]; return CLLocationCoordinate2DMake(latitude, longitude); } - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { MKCoordinateSpan span = MKCoordinateSpanMake(0.005, 0.005); MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.location.coordinate, span); [mapview setRegion:region]; [mapview setCenterCoordinate:userLocation.coordinate animated:YES]; NSString *baseUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%@&sensor=true", mapview.userLocation.location.coordinate.latitude, mapview.userLocation.location.coordinate.longitude, @"24.1620661,72.394131"]; //http://maps.googleapis.com/maps/api/directions/json?origin=23.030000,72.580000&destination=23.400000,72.750000&sensor=true NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSLog(@"%@",url); NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSError *error = nil; NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; NSArray *routes = [result objectForKey:@"routes"]; NSLog(@"%@",routes); NSDictionary *firstRoute = [routes objectAtIndex:0]; NSDictionary *leg = [[firstRoute objectForKey:@"legs"] objectAtIndex:0]; NSDictionary *end_location = [leg objectForKey:@"end_location"]; NSLog(@"dDDDDDD>>>>>>%@",leg); double latitude = [[end_location objectForKey:@"lat"] doubleValue]; double longitude = [[end_location objectForKey:@"lng"] doubleValue]; CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude); MKPointAnnotation *point = [[MKPointAnnotation alloc] init]; point.coordinate = coordinate; point.title = [leg objectForKey:@"end_address"]; point.subtitle = @"I'm here!!!"; [self.mapview addAnnotation:point]; NSArray *steps = [leg objectForKey:@"steps"]; int stepIndex = 0; CLLocationCoordinate2D stepCoordinates[1 + [steps count] + 1]; stepCoordinates[stepIndex] = userLocation.coordinate; for (NSDictionary *step in steps) { NSDictionary *start_location = [step objectForKey:@"start_location"]; stepCoordinates[++stepIndex] = [self coordinateWithLocation:start_location]; if ([steps count] == stepIndex){ NSDictionary *end_location = [step objectForKey:@"end_location"]; stepCoordinates[++stepIndex] = [self coordinateWithLocation:end_location]; } } MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:stepCoordinates count:1 + stepIndex]; [mapview addOverlay:polyLine]; CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake((userLocation.location.coordinate.latitude + coordinate.latitude)/2, (userLocation.location.coordinate.longitude + coordinate.longitude)/2); }]; }
然后实现MKMapViewDelegate的方法 – (MKOverlayView *)mapView:viewForOverlay:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay { MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay]; polylineView.strokeColor = [UIColor colorWithRed:204/255. green:45/255. blue:70/255. alpha:1.0]; polylineView.lineWidth = 1; return polylineView; } - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation { static NSString *annotaionIdentifier=@"annotationIdentifier"; MKPinAnnotationView *aView=(MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotaionIdentifier ]; if (aView==nil) { aView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotaionIdentifier]; aView.pinColor = MKPinAnnotationColorRed; aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; // aView.image=[UIImage imageNamed:@"arrow"]; aView.animatesDrop=TRUE; aView.canShowCallout = YES; aView.calloutOffset = CGPointMake(-5, 5); } return aView; }
First of all Add frame work 1 Foundation.framework 2 CoreGraphics.framework 3 CoreLocation.framework 4 MapKit.framework
然后创buildnsobject文件喜欢看…. TrailsMap.h文件
#import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interface TrailsMap : NSObject<MKAnnotation> { CLLocationCoordinate2D coordinate; NSString *title; NSString *image; NSString *subtitle; } @property (nonatomic, readonly) CLLocationCoordinate2D coordinate; @property (nonatomic,copy) NSString *title; @property (nonatomic,copy) NSString *image; @property (nonatomic,copy) NSString *subtitle; - (id)initWithLocation:(CLLocationCoordinate2D)coord;
TrailsMap.m
#import "TrailsMap.h" @implementation TrailsMap @synthesize coordinate,title,image,subtitle; - (id)initWithLocation:(CLLocationCoordinate2D)coord{ self = [super init]; if (self) { coordinate = coord; } return self; }
现在在mainview中创build编码请参阅..
ViewController.h
#import <UIKit/UIKit.h> #import <MapKit/MapKit.h> @interface ViewController : UIViewController<MKMapViewDelegate> @property (strong, nonatomic) IBOutlet MKMapView *MapView; @property (nonatomic, retain) MKPolyline *routeLine; @property (nonatomic, retain) MKPolylineView *routeLineView; -(void)LoadMapRoute; @end
最后在mainview.m文件中创build编码
ViewController.m
#import "ViewController.h" #import "TrailsMap.h" @interface ViewController () { NSData *alldata; NSMutableDictionary *data1; NSMutableArray *RouteLocation; NSMutableArray *RouteName; } @end @implementation ViewController @synthesize MapView,routeLine,routeLineView; - (void)viewDidLoad { [super viewDidLoad]; RouteName = [[NSMutableArray alloc] initWithObjects:@"Ahmedabad",@"Rajkot", nil]; RouteLocation = [[NSMutableArray alloc] initWithObjects:@"23.0300,72.5800",@"22.3000,70.7833", nil]; [self LoadMapRoute]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } //------------------------------------- // ************* Map ****************** //------------------------------------- -(void)LoadMapRoute { MKCoordinateSpan span = MKCoordinateSpanMake(0.8, 0.8); MKCoordinateRegion region; region.span = span; region.center= CLLocationCoordinate2DMake(23.0300,72.5800); // Distance between two address NSArray *coor1=[[RouteLocation objectAtIndex:0] componentsSeparatedByString:@","]; CLLocation *locA = [[CLLocation alloc] initWithLatitude:[[coor1 objectAtIndex:0] doubleValue] longitude:[[coor1 objectAtIndex:1] doubleValue]]; NSArray *coor2=[[RouteLocation objectAtIndex:1] componentsSeparatedByString:@","]; CLLocation *locB = [[CLLocation alloc] initWithLatitude:[[coor2 objectAtIndex:0] doubleValue] longitude:[[coor2 objectAtIndex:1] doubleValue]]; CLLocationDistance distance = [locA distanceFromLocation:locB]; NSLog(@"Distance :%.0f Meters",distance); NSString *baseUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%@&destination=%@&sensor=true", [RouteLocation objectAtIndex:0],[RouteLocation objectAtIndex:1] ]; NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; alldata = [[NSData alloc] initWithContentsOfURL:url]; NSError *err; data1 =[NSJSONSerialization JSONObjectWithData:alldata options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&err]; if (err) { NSLog(@" %@",[err localizedDescription]); } NSArray *routes = [data1 objectForKey:@"routes"]; NSDictionary *firstRoute = [routes objectAtIndex:0]; NSDictionary *leg = [[firstRoute objectForKey:@"legs"] objectAtIndex:0]; NSArray *steps = [leg objectForKey:@"steps"]; int stepIndex = 0; CLLocationCoordinate2D stepCoordinates[[steps count]+1 ]; for (NSDictionary *step in steps) { NSDictionary *start_location = [step objectForKey:@"start_location"]; double latitude = [[start_location objectForKey:@"lat"] doubleValue]; double longitude = [[start_location objectForKey:@"lng"] doubleValue]; stepCoordinates[stepIndex] = CLLocationCoordinate2DMake(latitude, longitude); if (stepIndex==0) { TrailsMap *point=[[TrailsMap alloc] initWithLocation:stepCoordinates[stepIndex]]; point.title =[RouteName objectAtIndex:0]; point.subtitle=[NSString stringWithFormat:@"Distance :%.0f Meters",distance]; [self.MapView addAnnotation:point]; } if (stepIndex==[steps count]-1) { stepIndex++; NSDictionary *end_location = [step objectForKey:@"end_location"]; double latitude = [[end_location objectForKey:@"lat"] doubleValue]; double longitude = [[end_location objectForKey:@"lng"] doubleValue]; stepCoordinates[stepIndex] = CLLocationCoordinate2DMake(latitude, longitude); TrailsMap *point=[[TrailsMap alloc] initWithLocation:stepCoordinates[stepIndex]]; point.title = [RouteName objectAtIndex:1]; point.subtitle=[NSString stringWithFormat:@"Distance :%.0f Meters",distance]; [self.MapView addAnnotation:point]; } stepIndex++; } MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:stepCoordinates count: stepIndex]; [MapView addOverlay:polyLine]; [MapView setRegion:region animated:YES]; } - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay { MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay]; polylineView.strokeColor = [UIColor colorWithRed:204/255. green:45/255. blue:70/255. alpha:1.0]; polylineView.lineWidth = 5; return polylineView; }
如果你想在地图上设置多个引脚,只需添加此代码。 Annotaion是Objectfile。
-(void)LoadMultiplePin { RouteName = [[NSMutableArray alloc] initWithObjects:@"Ahmedabad",@"Rajkot",@"Limdi", nil]; RouteLocation = [[NSMutableArray alloc] initWithObjects:@"23.0300,72.5800",@"22.3000,70.7833",@"22.5728,71.8114", nil]; MKCoordinateSpan span = MKCoordinateSpanMake(2.9, 2.9); MKCoordinateRegion region; region.span = span; region.center= CLLocationCoordinate2DMake(22.5728,71.8114); int cnt=RouteLocation.count; for (int p=0 ; p<cnt ; p++ ) { NSArray *coor=[[RouteLocation objectAtIndex:p] componentsSeparatedByString:@","]; CLLocationCoordinate2D location=CLLocationCoordinate2DMake([[coor objectAtIndex:0] doubleValue],[[coor objectAtIndex:1] doubleValue]); Annotaion *point=[[Annotaion alloc] initWithLocation:location]; point.title =[RouteName objectAtIndex:p]; [Map addAnnotation:point]; } [Map setRegion:region animated:YES]; }
通过使用这个代码你可以很容易地Drope两个引脚,并画这两个Pin之间的线享受快乐编码… 🙂
您可以使用MKPolyline在地图上绘制线条。
看到这个链接
http://spitzkoff.com/craig/?p=136
也:
https://github.com/kishikawakatsumi/MapKit-Route-Directions
这些都是您可以轻松参考的教程和开源库。 目前MapKit 不支持此function…
通过你的地址协调
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t { NSString* saddr = [NSString stringWithFormat:@"%f,%f", f.latitude, f.longitude]; NSString* daddr = [NSString stringWithFormat:@"%f,%f", t.latitude, t.longitude]; NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps? output=dragdir&saddr=%@&daddr=%@", saddr, daddr]; // NSString* apiUrlStr = @"http://maps.google.com/maps?output=dragdir&saddr=40.769264,-73.958995&daddr=47.286522,-122.312932"; NSURL* apiUrl = [NSURL URLWithString:apiUrlStr]; NSLog(@"api url: %@", apiUrl); NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:nil]; NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\\"([^\\\"]*)\\\"" capture:1L]; return [self decodePolyLine:[encodedPoints mutableCopy]]; } -(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded { [encoded replaceOccurrencesOfString:@"\\\\" withString:@"\\" options:NSLiteralSearch range:NSMakeRange(0, [encoded length])]; NSInteger len = [encoded length]; NSInteger index = 0; NSMutableArray *array = [[NSMutableArray alloc] init]; NSInteger lat=0; NSInteger lng=0; while (index < len) { NSInteger b; NSInteger shift = 0; NSInteger result = 0; do { b = [encoded characterAtIndex:index++] - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = [encoded characterAtIndex:index++] - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); lng += dlng; NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5]; NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5]; printf("[%f,", [latitude doubleValue]); printf("%f]", [longitude doubleValue]); CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]]; [array addObject:loc]; } return array; } -(void) updateRouteView:(UIColor *)clr { CGContextRef context =CGBitmapContextCreate(nil,routeView.frame.size.width,routeView.frame.size.height,8,4 * routeView.frame.size.width,CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast); CGContextSetStrokeColorWithColor(context, clr.CGColor); CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0); CGContextSetLineWidth(context, 3.0); for(int i = 0; i < routes.count; i++) { CLLocation* location = [routes objectAtIndex:i]; CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView]; if(i == 0) { CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y); } else { CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y); } } CGContextStrokePath(context); CGImageRef image = CGBitmapContextCreateImage(context); UIImage* img = [UIImage imageWithCGImage:image]; routeView.image = img; CGContextRelease(context); }
在这里你必须计算出它的纬度和经度的路线,然后在MapView上绘制多边形线……..我在我的应用程序中做这个事情….我在mapview上绘制所有信息的路线….
在这里,如果你使用MapKit,也使用RagexKitLite,那么对于你来说太简单了,只需要获得RagexKitLite的Demo。
我从@graver那里得到了很好的答案,并且为Swift 3做了这个:
// Called from viewDidLoad func setupMap() { mapView.delegate = self // BusStop implements the MKAnnotation protocol, I have an array of them let routeCoordinates = busStops.map({ $0.coordinate }) let routeLine = MKPolyline(coordinates: routeCoordinates, count: routeCoordinates.count) mapView.setVisibleMapRect(routeLine.boundingMapRect, animated: false) mapView.add(routeLine) } // MARK: MKMapViewDelegate func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { if let polyline = overlay as? MKPolyline { let polylineRenderer = MKPolylineRenderer(overlay: polyline) polylineRenderer.strokeColor = .blue polylineRenderer.lineWidth = 3 return polylineRenderer } return MKOverlayRenderer(overlay: overlay) }