Thought it was about time I stepped on the mashup bandwagon, a good number of years after the bandwagon had set out on it’s journey.
I’d be wanting to play with a mapping JavaScript API for some time and had seen some examples of people using the Google maps API with live traffic CCTV images from Transport for London (TfL). I decided to try and reproduce one of these mashups using the Nokia Maps API. Here’s a screen shot of the mashup in action:
Displaying a Nokia map
The first step was to display a panable, zoomable map using the Nokia maps API. In order to use this service you need to register as a developer with Nokia and then registe your username for access to the Location API.
Once registered it only takes a small amount of code to display a map.
Include this in the HTML head tag.
<meta http-equiv="X-UA-Compatible" content="IE=7; IE=EmulateIE9" /> <!-- load the api --> <script src="http://api.maps.nokia.com/2.2.1/jsl.js" type="text/javascript" charset="utf-8"></script>
And the following in the HTML body tag.
<!--This div tag will contain the map --> <div id="map" style="z-index: -1; left: 0px; width: 100%; height: 80%; position: absolute;"></div> <script type="text/javascript"> // Set up is the credentials to use the API nokia.Settings.set("appId", "your-appid"); nokia.Settings.set("authenticationToken", "your-auth-token"); var map = new nokia.maps.map.Display( document.getElementById("map") ); </script>
To add some useful functionality to the map such as zoom controls and the ability to view satellite imagery add the behaviours to the optional components parameter. The map can also be centered and the initial scale set as follows.
var map = new nokia.maps.map.Display( document.getElementById("map"), { components: [ // Behavior collection new nokia.maps.map.component.Behavior(), new nokia.maps.map.component.ZoomBar(), new nokia.maps.map.component.Overview(), new nokia.maps.map.component.TypeSelector(), new nokia.maps.map.component.ScaleBar() ], // Zoom level for the map 'zoomLevel': 10, // Map center coordinate on London 'center': [51.5, -0.1167] } );
Adding CCTV information from TfL
The CCTV images for London are supplied by TfL as part of their open data initiative (Transport Data Service). In order to get access you need to register for the service here.
The next step was to access the TfL CCTV service to get the camera information using the link provided by TfL. The service returns xml data which looks like this:
<?xml version="1.0" encoding="utf-8"?> <syndicatedFeed> <header> <identifier>TfL Traffic Cameras</identifier> <version>0.1</version> <publishDateTime>2012-09-15T16:31:17Z</publishDateTime> <author>digital@tfl.gov.uk</author> <owner>Transport for London</owner> <refreshRate>1</refreshRate> <max_Latency>10</max_Latency> <timeToError>10</timeToError> <overrideMessage /> <errorMessage /> <feedInfo></feedInfo> <logo>http://www.tfl.gov.uk/tfl-global/images/roundel.gif</logo> </header> <cameraList updated="1347726677"> <rooturl>/tfl/livetravelnews/trafficcams/cctv/</rooturl> <camera id="00001.02645" available="true"> <corridor>A205</corridor> <location>Ram St/Barchard St</location> <currentView>Ram St N/B</currentView> <file>0000102645.jpg</file> <captureTime>2012-09-15T16:30:29Z</captureTime> <easting>525706</easting> <northing>174806</northing> <lat>51.458282</lat> <lng>-0.1920207</lng> <osgr>TQ257748</osgr> <postCode>SW18 1TJ</postCode> </camera>
As you can see the data returned by the TfL CCTV service contains camera locations (lat longs and OS grid) and the image URLs.
Following on from the Twitter Vote Thingy I used AJAX in a main page (nokiamap_with_tfl_cams.html) to call some php (gettraffic_cams.php) which would access the TfL service via a class (traffic_cam_class.php). gettraffic_cams.php simply instantiates the class, calls it’s getCams() method and echos the result.
Like the Twitter Vote Thingy the getCams() method uses cURL to access the service URL.
The xml response is parsed using the php function simplexml_load_string e.g.
$xml = simplexml_load_string($response);
The xml is then iterated and a JSON string is constructed containing all the camera information. This is then returned to gettraffic_cams.php.
The javscript function gotCams is called when the state of the AJAX object changes i.e. when some data has been received. On receipt the JSON object string containing camera locations is parsed.
Each location is added to a collection of ‘map markers’. When setting up each map marker an ‘infobubble’ can be added to the marker object which displays some HTML (in this case an iframe containing the camera image) when the map marker is clicked. A listener is added to the map marker to handle this (see the addInfoBubble function).
//Called every time our XmlHttpRequest objects state changes. function gotCams() { //Check to see if the XmlHttpRequests state is finished. if (receiveReq.readyState == 4) { var cams = JSON.parse(receiveReq.responseText); for (var i = 0; i < cams.length - 1; i++) { //add marker if lat and long are not zero length if (cams[i].lat != '' && cams[i].lng != '') { var lat_long = new nokia.maps.geo.Coordinate(parseFloat(cams[i].lat), parseFloat(cams[i].lng)); var marker = new nokia.maps.map.StandardMarker(lat_long); var myHTMLcontent = "<div class=\"myHtmlContent\">"+"<iframe width='370' height='310' src='" + cams[i].file_location + "' frameborder='0' allowfullscreen></iframe>"+"</div>"; addInfoBubble(infoBubbles, marker, myHTMLcontent); //document.getElementById("debug").innerHTML = document.getElementById("debug").innerHTML + ' ' + cams[i].location + ' ' + cams[i].lat + ' ' + cams[i].lng; camContainer.objects.add(marker); } } map.objects.add(camContainer); } //Adds an info bubble displaying html to a marker function addInfoBubble(infoBubbles, marker, html) { marker.html = html; //Add click listener to marker. Display info bubble on click. marker.addListener("click", function(evt) { infoBubbles.addBubble(evt.target.html, evt.target.coordinate); }, false );
Adding Nokia real time traffic
Adding the capability to display live traffic information on top of the map is easy. Just add the following to the behaviour collection. This adds a car icon in the top right hand corner of the map. When this is clicked current traffic conditions are shown as coloured roads.
new nokia.maps.map.component.Traffic ()
In order to carry out this mini-adventure I found the following resources really useful:
http://www.developer.nokia.com/Community/Wiki/Nokia_Maps_API_-_Add_Maps_To_Any_Web_Page
http://www.developer.nokia.com/Community/Wiki/Nokia_Maps_API_-_How_to_add_map_markers
http://www.developer.nokia.com/Community/Wiki/Nokia_Maps_API_-_How_to_add_an_HTML_InfoBubble_on_the_map