It is the middle of September already. This month the Mozilla Dev Derby is focused on geolocation, and I decided to participate again after the not-so-exiting result with the Websockets derby.

mozilla dev derby

This time I wanted to come up with something simple but at the same time nice and effective. I thought a game experience build with HTML5 and the geolocation support would have been a nice idea. After thinking for a while about what I could implement I came up with this Find your Tile idea. In Find you Tile users are shown 3 map tiles - in satellite view. One is centered on their current location (detected via the geolocation API) and the other two are centered on a random city picked from a static list of more than 600 cities around the world.

find your tile

The goal for players is to pick the right map tile for their location. Nothing super exiting but still a demonstration of the cool stuff you can do by using a couple of interesting APIs together. If the player gets the answer wrong, along with the you picked the wrong one message a link to the Wikipedia page corresponding to the city where the wrongly picked tile is centered is provided. This way, in addition to being a game experience it is also a learning experience, as the player has the possibility to discover new cities and read all about them in the best encyclopedia in the world.

In this project I decided not to use jQuery or any other libraries. Instead I wrote everything in pure JavaScript, and since the demo only targets modern browsers I could use stuff like document.querySelector and document.querySelectorAll (IE >= 8), or array.forEach (IE >= 9) and of course navigator.geolocation (IE >= 8) since that was the point of the demo. I also added some nice animation effects with CSS3. I have to say it was fun. jQuery is very very convenient, it always makes our life easy. But it is not always appropriate for the use case (it should always be avoided on mobile for instance), so it is good to learn how to live without it. And this was the perfect excuse to prove I could do it.

The implementation is very simple, and does not require much explanation. The code is open source and available on Github.

To retrieve map tiles corresponding to the desired location I used the RESTful Maps API by Nokia. It is pretty nicely done and it has many customization options. Register your API key and play with this and the other APIs. Making things with maps can be fun. Like when thingsinjars and I built Soundscape.

To generate random tiles instead I had to Google for a while until I found a list of cities with their coordinates. I luckily found one that also includes the Wikipedia handle, so I could add the link to the Wikipedia page as well. Initially I thought I would just randomly generate a coordinate pair and center the two random tiles in there. But since there are approximately 70% chances of generating tiles that are just shades of blue, as 71% of the planet’s surface is covered by oceans and smaller seas I decided to go for the static list. Which I had to manually parse and go through all the cities to geocode them, as most of the coordinates initially in the list were for some reason wrong. Nothing that a simple Node.js script can’t do though.

One thing that I like a lot is the flipping animation of the map tiles. The HTML elements are initially rotated 180 degrees around the Y axes, so the white back is shown. Once the image.onload event is fired on each of the images, JavaScript adds the back CSS class to the element. At that point a CSS transition happens and the card smoothly flips. Awesome. Here is how you do it:

/*The element containing the tile*/
ol li {
    border: 15px solid #fff;
    box-shadow: 0 0 8px #ddd;
    width: 200px;
    height: 200px;
    display: inline-block;
    margin: 5px 20px;
    cursor: pointer;
    opacity: 0.9;
    position: relative;
    z-index: 95;

    /*The transform-style CSS property determines if the children
    of the element are positioned in the 3D-space or are
    flattened in the plane of the element.*/

    -webkit-transform-style: preserve-3d;
    -moz-transform-style: preserve-3d;
    -ms-transform-style: preserve-3d;
    transform-style: preserve-3d;

    /*Configure the transition*/
    -webkit-transition: all 1.0s ease;
    -moz-transition: all 1.0s ease;
    -ms-transition: all 1.0s ease;
    transition: all 1.0s ease;

    /*Initially flipped so the visible part is the back*/
    -webkit-transform: rotateY(180deg);
    -moz-transform: rotateY(180deg);
    -ms-transform: rotateY(180deg);
    transform: rotateY(180deg);

    /*Determines whether or not the back face of the element is visible
    when facing the user. The back face of an element always is
    a transparent background, letting, when visible,
    a mirror image of the front face be displayed.*/
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    backface-visibility: hidden;

    /*The rotation axis will be 30% from the left*/
    -webkit-transform-origin: 30%;
    -moz-transform-origin: 30%;
    -ms-transform-origin: 30%;
    transform-origin: 30%;
}

/*When back class is applied do the rotation*/
ol li.back {
    -webkit-transform: rotateY(0deg);
    -moz-transform: rotateY(0deg);
    -ms-transform: rotateY(0deg);
    transform: rotateY(0deg);
}

Lots of CSS, but mostly because of the prefixed rules. But in general pretty simple to understand.

//el is an img element
el.onload = function(){
    this.style.display = 'block';
    //Add the back class to trigger CSS transition
    this.parentNode.classList.add('back');
};

Here we go. With some simple JavaScript and CSS code and Nokia Maps API I built my demo for the Mozilla Dev Derby of this month. Enjoy it!

Note: I just realized the demo does not work in IE, not even IE9. Unfortunately the element.classList property (documented here) is not supported by IE. Oh well.

blog comments powered by Disqus