The Google Maps API V3

Ossama Alami, Geo Developer Advocate
@ossamaalami @googlemapsapi

What are we learning today?

Google Maps API v3

“Every millisecond counts”

Google User Experience Guidelines
http://www.google.com/corporate/ux.html

Maps API v3

IE7+, FF3+, Safari4+, Chrome, Android, iPhone, iPad
Mobile
Performance
No more API keys!

Before we get started...

+

=

Awesome!

A Map!
HTML
<!DOCTYPE html>
<html>
  <head>...</head>
  <body>
    <div id="map"></div>
  </body>
</html>
CSS
<style type="text/css">
html, body {
  height: 100%;
  margin: 0;
}

#map {
  height: 100%;
}
</style>
Javascript
<script type="text/javascript"
  src="http://maps.google.com/maps/api/js?sensor=false"></script>

<script type="text/javascript">
/**
 * Called on the initial page load.
 */
function init() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 14,
    center: new google.maps.LatLng(-33.866, 151.195),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });
}

// Register an event listener to fire when the page finishes loading.
google.maps.event.addDomListener(window, 'load', init);
</script>
A Map!
Mobile Map!
Localization
  <script type="text/javascript"
    src="http://maps.google.com/maps/api/js?sensor=false
    &language=es"></script>
http://code.google.com/apis/maps/faq.html#languagesupport
Geolocation
Javascript
function getUsersLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      var pos = new google.maps.LatLng(position.coords.latitude,
        position.coords.longitude);
      map.panTo(pos);
    }, function() {
      // Can find the users location
    });
  }
}
Markers
Javascript
var userLocationMarker = new google.maps.Marker();
navigator.geolocation.getCurrentPosition(function(position) {
  var pos = new google.maps.LatLng(position.coords.latitude,
    position.coords.longitude);
  map.panTo(pos);
  userLocationMarker.setPosition(pos);
  userLocationMarker.setMap(map);
}, function() {
  // Can find the users location
});
Custom Markers
Javascript
var icon = new google.maps.MarkerImage('my-location.png',
  new google.maps.Size(14, 14), // Image Size
  new google.maps.Point(0, 0), // Origin
  new google.maps.Point(7, 7)); // Anchor

var userLocationMarker = new google.maps.Marker({
  icon: icon
});
Overlays
Javascript
var accuracyCircle = new google.maps.Circle({
  fillColor: '#0000ff',
  fillOpacity: 0.1,
  strokeColor: '#0000ff',
  strokeOpacity: 0.3,
  strokeWeight: 1
});
accuracyCircle.bindTo('center', userLocationMarker, 'position');
function getUsersLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      var pos = new google.maps.LatLng(position.coords.latitude,
        position.coords.longitude);
      map.panTo(pos);
      userLocationMarker.setPosition(pos);
      accuracyCircle.setRadius(position.coords.accuracy);
      accuracyCircle.setMap(map);
      ...
Custom Controls
CSS
.button {
  background: #fff;
  border: 1px solid #000;
  margin-top: 5px;
  -webkit-box-shadow: inset -1px -1px 1px #707070;
  font: 12px Arial, sans-serif;
  padding: 1px 4px;
  cursor: pointer;
}
Javascript
var userLocation;
navigator.geolocation.watchPosition(setUsersPosition);
function setUsersPosition(position) {
  var pos = new google.maps.LatLng(position.coords.latitude,
    position.coords.longitude);
  userLocation = pos;
  userLocationMarker.setPosition(pos);
  accuracyCircle.setRadius(position.coords.accuracy);
}
function addGoToUsersLocationButton() {
  var button = document.createElement('DIV');
  button.className = 'button';
  button.innerHTML = 'My Location';
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(button);
  google.maps.event.addDomListener(button, 'click', function() {
    if (userLocation) {
      map.panTo(userLocation);
    }
  });
}
What do we have so far?
Adding a shop
Javascript
function addAddNewShopButton() {
  var button = document.createElement('DIV');
  button.className = 'button';
  button.innerHTML = 'Add Shop';
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(button);

  google.maps.event.addDomListener(button, 'click', showNewShopForm);
}
Using jQuery
function addNewShopButton() {
  var button = $('<div class="button">Add Shop</div>');
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(button[0]);
  $(button).click(showNewShopForm);
}
Javascript
var newShopMarker;
var newShopInfoWindow;
function addMarkerAndInfoWindow() {
  var formHTML = '<div id="add-new-shop-form">...</div>';
  newShopInfoWindow = new google.maps.InfoWindow({
    content: formHTML
  });

  newShopMarker = new google.maps.Marker();

  google.maps.event.addListener(map, 'click', function(mouseEvent) {
    newShopMarker.setPosition(mouseEvent.latLng);
  });
}
function showNewShopForm() {
  newShopMarker.setPosition(map.getCenter());
  newShopMarker.setMap(map);
  newShopInfoWindow.open(map, newShopMarker);
}
Reverse Geocoding
Javascript
function reverseGeocodeNewShopMarker() {
  var geocoder = new google.maps.Geocoder();
  var request = {latLng: newShopMarker.getPosition()};

  geocoder.geocode(request, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      var address = results[0].formatted_address;
      document.getElementById('new-shop-address').value = address;
    }
  });
}
google.maps.event.addListener(map, 'click', function(e) {
  ...
  reverseGeocodeNewShopMarker();
});
Saving a shop
Javascript
var shopIcon = new google.maps.MarkerImage('coffee.png',
  new google.maps.Size(32, 37));
function saveShop() {
  var position = newShopMarker.getPosition();

  // Gather form values and AJAX post to save the store

  newShopMarker.setMap(null);
  newShopInfoWindow.close();

  var marker = new google.maps.Marker({
    position: position,
    map: map,
    icon: shopIcon
  });
}
google.maps.event.addListener(newShopInfoWindow, 'domready', function() {
  var saveButton = document.getElementById('new-shop-save');
  google.maps.event.addDomListener(saveButton, 'click', saveShop);
});
Finding Shops
Javascript
google.maps.event.addListener(map, 'idle', loadStoresInView);
function loadStoresInView() {
  var bounds = map.getBounds().toUrlValue();

  // Do an AJAX call to get stores in the bounds
  // Call addStores on success
}
Javascript
function addStores(shops) {
  var d = new Date();
  var wasAdded = d.getTime();
  for (var i = 0, shop; shop = shops[i]; i++) {
    if (shopMarkers[shop.key]) {
      shopMarkers[shop.key]._wasAdded = wasAdded;
    } else {
      var marker = addStoreMarker(shop);
      marker._wasAdded = wasAdded;
      shopMarkers[shop.key] = marker;
    }
  }

  for (var key in shopMarkers) {
    if (shopMarkers[key]._wasAdded != wasAdded) {
      shopMarkers[key].setMap(null);
      delete shopMarkers[key];
    }
  }
}
Javascript
function addStoreMarker(shop) {
  var position = new google.maps.LatLng(shop.lat, shop.lng);
  var marker = new google.maps.Marker({
    position: position,
    map: map,
    title: shop.name,
    icon: shopIcon
  });
  return marker;
}
Directions
Javascript
var directionsService = new google.maps.DirectionsService();
var directionsRenderer = new google.maps.DirectionsRenderer({
  suppressMarkers: true,
  map: map
});
function getDirectionsTo(shop) {
  var request = {
    origin: userLocationMarker.getPosition(),
    destination: shop.address,
    travelMode: google.maps.DirectionsTravelMode.WALKING
  };

  directionsService.route(request, function(result, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      directionsRenderer.setDirections(result);
    }
  });
}
whereiscoffee.appspot.com
whereiscoffee.appspot.com
What Did We Learn?
Map
Markers, Overlays, Controls
Map Events
Getting User's Location
Geocoding
Directions
What else is there?
Polys
Elevation service
Traffic & Bicycling layers
KML & Fusion tables layers
Styled maps
Street view
Custom map types
...
Street View
Custom Street View
Custom Street View
function getCustomTileUrl(pano, x, y, z) {
  return 'http://my_server/tiles/tile_' + z + '_' + x + '_' + y + '.jpg';
};
Lastly


Questions?

@ossamaalami @googlemapsapi