It’s been an interesting passed two months, which is my immediate excuse for not posting any sooner. Not much exciting happened, except for one thing: our OFFF Appp.
About half a year ago, we at Somewhat asked Héctor (the organiser of OFFF) wether we could do their 2012 app. He gladly agreed, and about two months ago, we started working on the app. After weeks of experimenting, UI prototyping, and lots of coding, our OFFF Appp got released. And now, about a month after release, we had over 3000 visits, won and FWA Mobile of the Day, and still getting new likes and mentions on our movie.
I have to admit I couldn’t be happier with the result. Many thanks go out to the entire Somewhat Team, especially Matilda with who it was fantastic to work with, Héctor and the entire OFFF Team for giving us the chance to make this app, for their hospitality and for letting us give our lecture and workshop during a fantastic three day festival.
I quickly wanted to go over the development of this app, for those who are interested. Before I give my explanation, you have to know a few things: first of all, I’m not a professional web developer. I do this as a hobby, I love to do it, and I got the chance from Somewhat to develop this app since time was running out and it was hard finding a freelance developer who could build this app. Secondly, this is my first project where I use canvas to animate stuff. I’m quite sure there are far better ways to do this which I don’t know of now. So apologies if I’m describing a terrible methodology of coding, and do enlighten me with how I could’ve done this better. Let’s start…
There were a few areas I had to develop: drawing and animating the different sliders, and the big wheel for navigating, enabling interaction via touch or mouse, making the app responsive and work on different devices and resolutions, and lastly adding a back-end to it and making sure that data was available offline.
Drawing and animating the different sliders and wheels
First thing I did was get me a book on canvas. I started to learn the different ways of drawing and after learning about the arc-function, I got the circle drawn pretty quickly. In the end it’s a lot of basic trigonometry that makes everything happen. The curved text I had to do with images, since I couldn’t find a good way to write text on a curved line.
The app works with different states for where it is. There’s a state for when you’re viewing the coloured circle, when the circle animates to the top, when you switch between the days, … These states also define which listeners are active, which I’ll talk about later.
In the beginning I drew everything on one canvas. All animations, all circles, everything was drawn on one canvas that took up almost the entire screen. Obviously, this resulted in a very slow working app. It worked fine on a desktop computer, but lacked on mobile. I first tried to optimise it through drawing less lines, making the canvas smaller, … But nothing seemed to do the trick. After doing some more research, I came across this amazing article on how to optimise your canvas animations. So I followed the advice: I made separate canvases for the coloured circle, the indicators of time and day in the background and a separate canvas for every slider. I made sure the canvases only animated when something changed. And I optimised the way of drawing so it had to do less calculations per iteration.
The optimised app started working a lot quicker, but still there was a big difference between an iPad2/iPhone4(S) and other new Android phones such as the Galaxy SII or the latest Google Nexus. Even though they have similar specs, the iOS devices were far better in handling the animations. The reason why is because Safari uses hardware accelerated graphics to do the animations which really shows when animating in canvas.
Enabling interaction via touch or mouse
When we defined the user interactions, we had a few gestures in mind that we wanted to use. Obviously navigating over the circle happened by scrolling over it, so I needed an event for when you start touching the screen, when you moved, and when you stopped touching it. We also wanted to use swipes to left and right, and pinching your fingers together to go to the day view. Next to that we wanted it to work on as many devices as possible: iOS, Android, Windows Mobile, Blackberry, Bada, but also regular desktop computers.
Trying to find a touch-library that would work on all those devices and enable all those gestures was pretty difficult. We learnt a lot about devices. For example: Windows Mobile doesn’t support any other gestures than a simple tap. So optimising for these devices was pretty much near impossible. Blackberry had a similar problem: we didn’t have a good Blackberry to test on, and we realised the target group probably wouldn’t have a Blackberry. So we decided not to optimise for these devices either. To compensate though, we made http://offf.somewhat.cc/table which would work on those devices, and older mobile browsers who wouldn’t support canvas or touch events.
So we were left with iOS, Android and desktop browsers. Tons of libraries available, but not many that enabled all gestures on all devices with a simple event. The one I thought was best, was jQuery Mobile. It has simple events for touch start, move, end and for tap that works on all devices + desktop computers. The disadvantage is pinching wasn’t included. So we decided to kill that gesture and use a tap instead (sadly enough). Unfortunately, a few weeks after our app got released, I learnt about Hammer.js which does allow pinching on both Android and iOS.
So that’s how it works. jQuery Mobile listens to several gestures, and calls events listeners that are (dis)activated depending on what state the app is in. The listener gets information from the event, and uses that to redraw the canvases to show interaction. Fairly simple if you think about it…
Making the app responsive and work on different devices and resolutions
Although CSS3 has media-queries, making the app responsive wasn’t as easy as first thought. From what I know, you have to give a canvas an absolute width and height. You can’t give it a percentage, which is quite annoying when you want to make it responsive. After much testing and optimising, I went for a canvas of 768px wide, and about 900px heigh. That way it would look crisp on high-resolution smartphones such as an iPhone4(S), and it would still look good on most tablets and desktop computer, including an iPad2. The disadvantage was the low quality on an iPad3. I had to go up to 1536px in width and +1800px in height to make it look crisp, and that showed significant delays on other devices. Hence the current resolution.
Apart from that, making it responsive was not that difficult. Using media-queries and relative sizes for everything made the app resize gracefully.
Adding a back-end to it and making sure that data was available offline
This was probably the easiest part. All data is saved on a simple MySQL database that we update manually (we only had to change the schedule once, so good call on not implementing a CMS). The data gets printed in a JSON format, and read through AJAX by the app. The image of the artist is loaded only when you view the artist.
The app also works offline by using HTML5’s offline feature. This is very easy to do: you create a manifest-file specifying all the files that need to be stores locally. The app downloads them once, and uses those file to make the app work without a data connection. HTML5’s offline feature includes a lot of events that get triggered, which make it easy to show wether your app is offline or able to connect to the server, how far the progress is in download, wether the download was successful or not, …
The biggest disadvantage of this feature though, is the fact that when you change once file on your server, for example the stylesheet, you need to update the manifest. And every browser will download every file again, even though only one file has been updated. This is quite annoying for an app that needs to work entirely offline. With all the code and images, the app is now about 25MB, which is a lot to download over a mobile connection. A solutions would’ve been to write a manuel manifest manager who would check what has been updated and only store new files. But since time and budget were short, I didn’t get the chance to implement it.
So that’s how it works in a nutshell (fairly large once though). I must admit, my code got a bit messy in the end, although I was using classes to separate everything well. If I’d do it again, I’d probably use a good MVC library to make the code cleaner, and better media-query management with a library like Harvey. But all in all, it was a great learning experience and I’m very happy with the result.
Again many thanks to the Somewhat Team, to Matilda and to friends and family who didn’t see me much during those two months, but still stayed in touch.