Playing with Geolocation and Konami

Ever since I started work on HybridLogic I’ve been dropping in Easter Eggs, adding quirky little things for those adventurous souls to find. With the latest version of HL though I really wanted to add something special, ideally using the famed Konami code trigger. In the end I created a very quick mash-up of some new technology to add a bit of fun to HL.

Before I begin, why not take a look at the finished product. (Up, up, down, down, left, right, left, right, b, a for those who don’t know the Konami code off by heart). A popup window appears that displays your location on a map along with your distance from the server this website is hosted on.

The cool part of all this is how the map determines your location. Using the W3C Geolocation API your browser (if given permission) can locate your current position and send it to a bit of JavaScript. Unfortunately not all browsers support this new aspect of the HTML 5 spec, in which case the code will fall back to the YQL Geo library which relies on IP based matching (not as accurate but still a fair approximation).

The code is based in large on the excellent tutorial by Mobile Tuts with a few amends. The core functions initialise the geolocation request and then await either a success or failure response. Hooking into these I could begin to add my own tweaks.

The first was to run the whole thing inside a modal pop-up. Rather than add the bulk of FancyBox or other large pop-up libraries I opted for the much more lightweight SimpleModal (2Kb!). Jury rigging a basic AJAX loader I soon had it up and calling the page.

When the geolocation object returns a successful co-ordinate set the real fun can begin. The first task was generating a Google Map of the users location. This is actually incredibly easy using the Google Static Maps API. The only difficulty was in converting the accuracy of the returned co-ordinates (returned as a distance in meters) to an appropriate zoom level.

Converting the decimal representation of the co-ordinates (such as 37.82612, -122.42254) to a more humane representation (37° 49′ 34″ N, 122° 25′ 21″ W) took a bit of GCSE maths. In effect you work out the minutes and seconds of the remaining parts. This sounds horrendous but the actual code is very simple:

[javascript]
jfunction decimal_to_hms(num) {
var parts = {};
parts.hours = parseInt(num);
num -= hms.hours;
num *= 60;
parts.minutes = parseInt(num);
num -= hms.minutes;
num *= 60;
parts.seconds = parseInt(num);
return parts;
}
[/javascript]

The last part was determining how far the visitor is from where my Linode server lives in London. The maths for this was quite a bit more complicated, using the ever faithful Haversine formula. In laymans terms it works out the distance between two points as if they were on a sphere which the Earth isn’t but for all intents and purposes can be considered to be so.

[javascript]
function distance_between_points(p1, p2) {
var r = 6371; // Earth’s radius in km
var d2r = Math.PI/180;
var dLat = (p1.latitude-p2.latitude)*d2r;
var dLon = (p1.longitude-p2.longitude)*d2r;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(p1.latitude*d2r) * Math.cos(p2.latitude*d2r) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return r * c;
}
[/javascript]

The rest of the development time was spent styling up the finished results. The trigger for the popup was handled by the wonderfully simple jQuery Konami Code plugin. Feel free to peruse the source and play around with the data available, I already have plans to tie this into a location-based service now the technology is finally coming of age.