So as I mentioned in my last post I’ve been playing with generating map overlays for the cycling videos I’ve been making while out training. I’d run into a rate limiting problem when using Google Maps static map API.
To work round this I thought I’d see what I could do using Openstreetmap. Openstreetmap doesn’t have a static image API so I’m going to try and build something similar using LeafletJS and a way to grab images of the pages generated.
<html> <head> <title>Maps</title> <link type="text/css" href="leaflet.css" rel="stylesheet"/> <script type="application/javascript" src="leaflet.js"></script> <style > #map { height: 250px; width: 250px; } </style> </head> <body> <div id="map"/> <script type="application/javascript"> function getUrlVars() { var vars = [], hash; var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); for(var i = 0; i < hashes.length; i++) { hash = hashes[i].split('='); vars.push(hash[0]); vars[hash[0]] = hash[1]; } return vars; } var args = getUrlVars(); var line = args["line"].split("|"); var last = line[(line.length - 1)]; var centre = [last.split(',')[0], last.split(',')[1]]; var map = L.map('map',{ zoomControl: false, zoom: 15 }); map.setView(centre, 15); L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 20, }).addTo(map); var latlngs = []; for (var i=0; i<line.length; i++) { latlngs.push(L.latLng(line[i].split(',')[0],line[i].split(',')[1])); } var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map); </script </body> </html>
This generates the map tiles and overlays the route, but it’s as a web page, now I needed a way to convert this into a PNG image. There are two options, html2canvas or PhantomJS. I decided to go with PhantomJS first. The following loads and renders the page and then generates a PNG image.
var page = require('webpage').create(); var system = require('system'); page.onConsoleMessage = function(msg, lineNum, sourceId) { //console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'); }; page.viewportSize = { width: 265, height: 250 }; var url = "file:///opt/share/playing/map-overlay/index.html?" + system.args[1]; console.log(url); page.open(url, function(){ setTimeout(function() { page.render(system.args[2]); phantom.exit(); },500); });
The coordinates for the line are passed in on the command line along with the file name to write the file to.
phantomjs --local-to-remote-url-access=true --max-disk-cache-size=1024 --disk-cache=true map.js [Path] [file name]
Running PhantomJS with the disk cache enabled should keep the load on the Openstreetmap servers to a minimum but I’m also looking at how easy it is to set up my own tile server.
I can now feed this in to the scripts I spun up last time.