Presentation given at the HighEdWeb 2010 Conference in Cincinnati
Resources
- Mobile Map Template
- Google Maps API v3 Documentation
- Google Maps API v3 Articles (includes iOS and Android application development how-to)
- Related Blog Posts
Presentation given at the HighEdWeb 2010 Conference in Cincinnati
I gave this presentation at the Penn State Web Conference 2010 on June 8.
What good is a map that you can zoom, click, stretch and interact with if you can’t take it with you? Let’s ask the visitor in the parking lot how cool your map is when they are trying to find the admissions office. Mobile users are everywhere – and growing. Can your map keep up?
This session explores how to use the new Google Maps V3 API to make all your mobile map dreams come true – including the one where you’re the campus hero for the stellar new iPhone/Android application. One map that just works everywhere.
Based on experiences with the Missouri State Map.
Download Presentation: One Map to Rule Them All
April 30, 2013 Update: Post and template updated to include a more modern application cache loading script as well as utilizing my GeolocationMarker code and the latest Maps API v3 options.
Developing a map for mobile devices presents unique challenges. Not only must your user interface work on a small screen and be optimized for touch, but your map needs to load fast.
Note: This article is about maps for iPhone and Android devices. Many of the techniques here are optimized for HTML5 browsers and will not work in Internet Explorer or older browsers. While techniques exist to support similar functionality on other browsers, they are beyond the scope of this article.
Speed to the user can be a tricky thing to measure. Do you measure until when your map, custom layers, markers and location are fully loaded? Or do you measure until the user can first interact with the map? Whatever the choice, it is important to provide feedback to the user so that they can at least see progress.
Script tags block page rendering until they are completely downloaded and processed. This can be a significant wait on slower devices when loading the Maps API during which time the user won’t see any progress. To allow your page to load first, dynamically add the Maps API on the DOMContentLoaded event. When you use this technique, you’ll need to add a callback parameter to the script source to know when the API has finished loading.
document.addEventListener('DOMContentLoaded', function () { var element = document.createElement('script'); element.src = 'http://maps.google.com/maps/api/js?sensor=true&callback=Initialize'; element.type = 'text/javascript'; var scripts = document.getElementsByTagName('script')[0]; scripts.parentNode.insertBefore(element, scripts); }, false); |
document.addEventListener('DOMContentLoaded', function () { var element = document.createElement('script'); element.src = 'http://maps.google.com/maps/api/js?sensor=true&callback=Initialize'; element.type = 'text/javascript'; var scripts = document.getElementsByTagName('script')[0]; scripts.parentNode.insertBefore(element, scripts); }, false);
Wait until the map has loaded to add custom layers, markers and other data. The tilesloaded event is a good place to start adding your data. This allows the user to see even more of the map load instead of waiting until everything is done. If your map script is in an external JavaScript file, you can dynamically add it right after initializing the map.
function Initialize() { var MapOptions = { zoom: 15, center: new google.maps.LatLng(37.20084, -93.28121), mapTypeId: google.maps.MapTypeId.ROADMAP, sensor: true }; map=new google.maps.Map( document.getElementById("map_canvas"), MapOptions); //Delay customizations until the map has loaded var element = document.createElement('script'); element.src = 'template.js'; element.type = 'text/javascript'; var scripts = document.getElementsByTagName('script')[0]; scripts.parentNode.insertBefore(element, scripts); } |
function Initialize() { var MapOptions = { zoom: 15, center: new google.maps.LatLng(37.20084, -93.28121), mapTypeId: google.maps.MapTypeId.ROADMAP, sensor: true }; map=new google.maps.Map( document.getElementById("map_canvas"), MapOptions); //Delay customizations until the map has loaded var element = document.createElement('script'); element.src = 'template.js'; element.type = 'text/javascript'; var scripts = document.getElementsByTagName('script')[0]; scripts.parentNode.insertBefore(element, scripts); }
This is basically caching on steroids. This has been covered elsewhere, but it should be mentioned that this alone makes a HUGE difference for return visits. There are a couple of things to keep in mind when developing a cache-manifest file:
Sample CACHE-MANIFEST file:
CACHE MANIFEST /examples/template.htm /examples/template.css /examples/template.js http://missouristate.info/images/2010/loading.gif http://missouristate.info/images/2010/map/gpsloc.png NETWORK: http://maps.gstatic.com/ http://maps.google.com/ http://maps.googleapis.com/ http://mt0.googleapis.com/ http://mt1.googleapis.com/ http://mt2.googleapis.com/ http://mt3.googleapis.com/ http://khm0.googleapis.com/ http://khm1.googleapis.com/ http://cbk0.googleapis.com/ http://cbk1.googleapis.com/ http://www.google-analytics.com/ http://gg.google.com/ http://csi.gstatic.com/ |
CACHE MANIFEST /examples/template.htm /examples/template.css /examples/template.js http://missouristate.info/images/2010/loading.gif http://missouristate.info/images/2010/map/gpsloc.png NETWORK: http://maps.gstatic.com/ http://maps.google.com/ http://maps.googleapis.com/ http://mt0.googleapis.com/ http://mt1.googleapis.com/ http://mt2.googleapis.com/ http://mt3.googleapis.com/ http://khm0.googleapis.com/ http://khm1.googleapis.com/ http://cbk0.googleapis.com/ http://cbk1.googleapis.com/ http://www.google-analytics.com/ http://gg.google.com/ http://csi.gstatic.com/
Note: The URLs listed above are subject to change without notice. When using the Google Maps API via SSL there are slightly different versions of the addresses.
Use the Google Page Speed tool to help optimize your site. While the suggestions are relevant to any site, they make a much bigger impact on mobile devices due to the high latency connections and device processor/memory constraints.
Not only must your map function on a small screen, but there is a wide variety of screen sizes among devices.
You want the map to fill the whole screen minus the space for any header/footer. You can use a CSS technique with conflicting absolute positions to avoid having to calculate height in JavaScript. This method will properly handle device rotation as well.
<div id="map_canvas" style="position:absolute;top:30px;bottom:50px;left:0;right:0;"></div> |
<div id="map_canvas" style="position:absolute;top:30px;bottom:50px;left:0;right:0;"></div>
Lack of feedback will frustrate your users. It’s rather simple to display a progress indicator to let your users know that the map is actually loading. Adding an overlay div to indicate loading is an easy way to show this. You can disable the loading div in the tilesloaded event.
Both Android phones and the iPhone support a number of link and meta tags for sites which are designed to function as an application. Here’s a list of the one’s most applicable to a map:
Tag | Name/Rel | Value | Supporting Device | Note |
---|---|---|---|---|
link | apple-touch-icon | Url of PNG Icon | iPhone and Android | Android doesn’t add gloss to icons |
link | apple-touch-icon-precomposed | Url of PNG Icon | iPhone and Android | The iPhone won’t add gloss to this icon |
link | app-touch-startup-image | Image to display while loading | iPhone | Only shows when the site has been saved then launched from the home screen. |
meta | apple-mobile-web-app-capable | “yes” | iPhone | Indicates that the site is designed to function as a standalone application (launched from the homescreen) without browser chrome. |
meta | viewport | initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0 | iPhone and Android | Indicates that the browser should display the site without scaling and disable zooming the entire page since the map handles zooming. |
Newer mobile devices (and now even laptops and desktops) come with high-density displays. To make full use of these, your map needs to use high resolution graphics. I have found that using CSS selectors based of the device-pixel density to be unreliable as there doesn’t seem to be a common meta viewport tag that will correctly report the density across all browsers. Instead, I’ve found it is just easier to make all images twice the size and scale them to 50% via CSS. Map markers and overlays can use a similar technique using the scaledSize property of the Icon object. Unfortunately at this point in time there is not a way to use high resolution icons in KML or Fusion Table Layers.
Congratulations to Matt Seigel, Web Programmer from the Office of Web and New Media, who was selected as University Relations Student Employee of the Month.
Matt was recognized for implementing the designs for the Missouri State Magazine web site. Early in the spring semester, Matt modified a Word Press blog install to support the issue based format of an online magazine and to handle the numerous features required. It was based upon this work that new plugins were made available in the main university blogs site for embedding media in a post.
Matt was also recognized for his work on shuttle tracking for the campus map. Implementing the display of the shuttles on the map required Matt to do a large amount of research and to collaborate with multiple other areas to make this project a success.
Please help me congratulate Matt on this much deserved recognition.