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>)annotation
draws 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