CS175
Chris Pollett
Nov 26, 2014
<!DOCTYPE html> <html> <head> <title>Location Test</title> </head> <body> <h1>Location Test</h1> <script type="text/javascript"> function mycallback(position) { alert("Your latitude is: " + position.coords.latitude); alert("Your longitude is: " + position.coords.longitude); alert("The accuracy is:" + position.coords.accuracy); } function error(msg) { if(msg) { alert(msg); } else { alert("that did not work"); } } if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(mycallback, error); } else { error('not supported'); } </script> </body> </html>
<!DOCTYPE html> <html> <head> <title>A Google Test</title> </head> <body onload="drawMap()"> <h1>A Google Map</h1> <div id="mymap"></div> <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> <!-- ?sensor=false means not determining location of map using a sensor--> <script type="text/javascript"> function drawMap() { var latlng = new google.maps.LatLng(37.375, -121.833); mapcanvas= document.getElementById("mymap"); mapcanvas.style.height = '400px'; mapcanvas.style.width = '600px'; var myOptions = { zoom: 15, center: latlng, mapTypeControl: false, navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}, mapTypeId: google.maps.MapTypeId.ROADMAP }; var map = new google.maps.Map( mapcanvas, myOptions); var marker = new google.maps.Marker({ position: latlng, map: map, title:"This is a great pin!" }); } </script> </body> </html>
<html> <body> <div id="mapdiv" style="width:400px; height:400px"></div> <script src="http://www.openlayers.org/api/OpenLayers.js"></script> <script> map = new OpenLayers.Map("mapdiv"); map.addLayer(new OpenLayers.Layer.OSM()); var lonLat = new OpenLayers.LonLat( -0.1279688 ,51.5077286 ) .transform( new OpenLayers.Projection("EPSG:4326"), // transform from project used by GPS map.getProjectionObject() // to Spherical Mercator Projection ); var zoom=16; var markers = new OpenLayers.Layer.Markers( "Markers" ); map.addLayer(markers); markers.addMarker(new OpenLayers.Marker(lonLat)); map.setCenter (lonLat, zoom); </script> </body> </html>
MapViewController.h is standard boiler plate, the implementation file has all the specifics:
(MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotationdraws the view when the annotations is tapped. If the view further has a callout, then
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)controlsets it up.
#import "MapViewController.h" #import "DetailViewController.h" #import "SFAnnotation.h" // annotation for the city of San Francisco #import "BridgeAnnotation.h" // annotation for the Golden Gate bridge #import "CustomAnnotation.h" // annotation for the Tea Garden @interface MapViewController () <MKMapViewDelegate> @property (nonatomic, weak) IBOutlet MKMapView *mapView; @property (nonatomic, strong) NSMutableArray *mapAnnotations; @property (nonatomic, strong) UIPopoverController *bridgePopoverController; @end #pragma mark - @implementation MapViewController - (void)gotoDefaultLocation { // start off by default in San Francisco MKCoordinateRegion newRegion; newRegion.center.latitude = 37.786996; newRegion.center.longitude = -122.440100; newRegion.span.latitudeDelta = 0.112872; newRegion.span.longitudeDelta = 0.109863; [self.mapView setRegion:newRegion animated:YES]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // restore the nav bar to translucent self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent; } - (void)viewDidLoad { [super viewDidLoad]; // create a custom navigation bar button and set it to always says "Back" UIBarButtonItem *temporaryBarButtonItem = [[UIBarButtonItem alloc] init]; temporaryBarButtonItem.title = @"Back"; self.navigationItem.backBarButtonItem = temporaryBarButtonItem; // create out annotations array (in this example only 3) self.mapAnnotations = [[NSMutableArray alloc] initWithCapacity:2]; // annotation for the City of San Francisco SFAnnotation *sfAnnotation = [[SFAnnotation alloc] init]; [self.mapAnnotations addObject:sfAnnotation]; // annotation for Golden Gate Bridge BridgeAnnotation *bridgeAnnotation = [[BridgeAnnotation alloc] init]; [self.mapAnnotations addObject:bridgeAnnotation]; // annotation for Japanese Tea Garden CustomAnnotation *item = [[CustomAnnotation alloc] init]; item.place = @"Tea Garden"; item.imageName = @"teagarden"; item.coordinate = CLLocationCoordinate2DMake(37.770, -122.4709); [self.mapAnnotations addObject:item]; [self allAction:self]; // initially show all annotations } #pragma mark - Button Actions - (void)gotoByAnnotationClass:(Class)annotationClass { // user tapped "City" button in the bottom toolbar for (id annotation in self.mapAnnotations) { if ([annotation isKindOfClass:annotationClass]) { // remove any annotations that exist [self.mapView removeAnnotations:self.mapView.annotations]; // add just the city annotation [self.mapView addAnnotation:annotation]; [self gotoDefaultLocation]; } } } - (IBAction)cityAction:(id)sender { [self gotoByAnnotationClass:[SFAnnotation class]]; } - (IBAction)bridgeAction:(id)sender { // user tapped "Bridge" button in the bottom toolbar [self gotoByAnnotationClass:[BridgeAnnotation class]]; } - (IBAction)teaGardenAction:(id)sender { // user tapped "Tea Gardon" button in the bottom toolbar [self gotoByAnnotationClass:[CustomAnnotation class]]; } - (IBAction)allAction:(id)sender { // user tapped "All" button in the bottom toolbar // remove any annotations that exist [self.mapView removeAnnotations:self.mapView.annotations]; // add all 3 annotations [self.mapView addAnnotations:self.mapAnnotations]; [self gotoDefaultLocation]; } #pragma mark - MKMapViewDelegate // user tapped the disclosure button in the bridge callout // - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control { // here we illustrate how to detect which annotation type was clicked on for its callout id <MKAnnotation> annotation = [view annotation]; if ([annotation isKindOfClass:[BridgeAnnotation class]]) { NSLog(@"clicked Golden Gate Bridge annotation"); DetailViewController *detailViewController = [[self storyboard] instantiateViewControllerWithIdentifier:@"DetailViewController"]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { // for iPad, we use a popover if (self.bridgePopoverController == nil) { _bridgePopoverController = [[UIPopoverController alloc] initWithContentViewController:detailViewController]; } [self.bridgePopoverController presentPopoverFromRect:control.bounds inView:control permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES]; } else { // for iPhone we navigate to a detail view controller using UINavigationController [self.navigationController pushViewController:detailViewController animated:YES]; } } } - (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation { MKAnnotationView *returnedAnnotationView = nil; // in case it's the user location, we already have an annotation, so just return nil if (![annotation isKindOfClass:[MKUserLocation class]]) { // handle our three custom annotations // if ([annotation isKindOfClass:[BridgeAnnotation class]]) // for Golden Gate Bridge { returnedAnnotationView = [BridgeAnnotation createViewAnnotationForMapView:self.mapView annotation:annotation]; // add a detail disclosure button to the callout which will open a new view controller page or a popover // // note: when the detail disclosure button is tapped, we respond to it via: // calloutAccessoryControlTapped delegate method // // by using "calloutAccessoryControlTapped", it's a convenient way to find out which annotation was tapped // UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; [rightButton addTarget:nil action:nil forControlEvents:UIControlEventTouchUpInside]; ((MKPinAnnotationView *)returnedAnnotationView).rightCalloutAccessoryView = rightButton; } else if ([annotation isKindOfClass:[SFAnnotation class]]) // for City of San Francisco { returnedAnnotationView = [SFAnnotation createViewAnnotationForMapView:self.mapView annotation:annotation]; // provide the annotation view's image returnedAnnotationView.image = [UIImage imageNamed:@"flag.png"]; // provide the left image icon for the annotation UIImageView *sfIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SFIcon.png"]]; returnedAnnotationView.leftCalloutAccessoryView = sfIconView; } else if ([annotation isKindOfClass:[CustomAnnotation class]]) // for Japanese Tea Garden { returnedAnnotationView = [CustomAnnotation createViewAnnotationForMapView:self.mapView annotation:annotation]; } } return returnedAnnotationView; } @end
DetailViewController.h is boilerplate, the implementation file loads the image of the Golden Gate breidge and draw its on the screen.
#import "DetailViewController.h" @implementation DetailViewController - (void)viewDidLoad { [super viewDidLoad]; // fit the our popover size to match our image size UIImageView *imageView = (UIImageView *)self.view; // this will determine the appropriate size of our popover self.preferredContentSize = CGSizeMake(imageView.image.size.width, imageView.image.size.height); self.title = @"Golden Gate"; // for this view controller we want a black style nav bar self.navigationController.navigationBar.barStyle = UIBarStyleBlack; } @end
To control the text next to our pins we use Annotations. For San Francisco the header looks like:
@interface SFAnnotation : NSObject+ (MKAnnotationView *)createViewAnnotationForMapView:(MKMapView *)mapView annotation:(id )annotation; @end
The implementation looks like:
#import "SFAnnotation.h" @implementation SFAnnotation - (CLLocationCoordinate2D)coordinate { CLLocationCoordinate2D theCoordinate; theCoordinate.latitude = 37.786996; theCoordinate.longitude = -122.419281; return theCoordinate; } - (NSString *)title { return @"San Francisco"; } // optional - (NSString *)subtitle { return @"Founded: June 29, 1776"; } + (MKAnnotationView *)createViewAnnotationForMapView:(MKMapView *)mapView annotation:(id)annotation { MKAnnotationView *returnedAnnotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:NSStringFromClass([SFAnnotation class])]; if (returnedAnnotationView == nil) { returnedAnnotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:NSStringFromClass([SFAnnotation class])]; returnedAnnotationView.canShowCallout = YES; // offset the flag annotation so that the flag pole rests on the map coordinate returnedAnnotationView.centerOffset = CGPointMake( returnedAnnotationView.centerOffset.x + returnedAnnotationView.image.size.width/2, returnedAnnotationView.centerOffset.y - returnedAnnotationView.image.size.height/2 ); } else { returnedAnnotationView.annotation = annotation; } return returnedAnnotationView; } @end
The header looks like:
#import <MapKit/MapKit.h> @interface BridgeAnnotation : NSObject+ (MKAnnotationView *)createViewAnnotationForMapView:(MKMapView *)mapView annotation:(id )annotation; @end
The implementation looks like:
#import "BridgeAnnotation.h" @implementation BridgeAnnotation - (CLLocationCoordinate2D)coordinate { CLLocationCoordinate2D theCoordinate; theCoordinate.latitude = 37.810000; theCoordinate.longitude = -122.477450; return theCoordinate; } // required if you set the MKPinAnnotationView's "canShowCallout" property to YES - (NSString *)title { return @"Golden Gate Bridge"; } // optional - (NSString *)subtitle { return @"Opened: May 27, 1937"; } + (MKAnnotationView *)createViewAnnotationForMapView:(MKMapView *)mapView annotation:(id)annotation { // try to dequeue an existing pin view first MKAnnotationView *returnedAnnotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:NSStringFromClass([BridgeAnnotation class])]; if (returnedAnnotationView == nil) { returnedAnnotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:NSStringFromClass([BridgeAnnotation class])]; ((MKPinAnnotationView *)returnedAnnotationView).pinColor = MKPinAnnotationColorPurple; ((MKPinAnnotationView *)returnedAnnotationView).animatesDrop = YES; ((MKPinAnnotationView *)returnedAnnotationView).canShowCallout = YES; } return returnedAnnotationView; } @end