iPhone

Important iOS CSS3 performance hint

Though it was speculated to be fixed with the iOS 4.2 release, it is still the case that on iPhone and iPad translate3d is hardware accelerated whereas translate is not.

So if you want to animate large images or content elements

#element.move { -webkit-transform:translate(10px, 100px); -webkit-transition:transform; }

is dog slow whereas

#element.move { -webkit-transform:translate3d(10px, 100px, 0px); -webkit-transition:transform; }

is blazingly fast.

As there is no real downside in using translate3d it should always be used to provide good performance on mobile devices.


ios 4.2 update with important mobile safari features

Apple released the new ios version 4.2 for iphone, ipod touch and ipad yesterday.

This update sports lots of new features and security fixes. Among others the mobile safari (webkit) feature set was seriously improved. It now features

  • The new Device Orientation API (Accelerometer access without phonegap)
  • Better HTML5 Form Support
  • New HTML5 events like onhashchange
  • Better SVG Support
  • ImageData Support for the Canvas API
  • The all WebSockets API – this one is huge
  • Partial support for XMLHttpRequest Level 2
  • And last but not least support for typed arrays is on the way

Looks like this update is really important for anyone developing webapps for the iphone/ipad. The only thing missing are detailed informations about tweaks to the hardware acceleration.

Now if only A1 would sell the iPhone 4 already. Bugs me that i can not test stuff on the retina display. Latest rumors are 29. November.


Accurate javascript geolocation with current (mobile) browsers

With GPS chipsets x as well as modern webbrowsers present in most mobile devices (iPhone and Android Phones, Tablets and even Notebooks) these days, it is surely time to start using geolocation with your webservices.

This is actually quite simple, as most current browsers (this as always excludes internet explorer) implement the W3C Geolocation API Specification. As seen in many tutorials, you simple check if the navigator.geolocation object exists, call navigator.geolocation.getCurrentPosition(my_callback) and get the current location of your user.

Nice and easy, but there is one little Problem: on most devices, this can lead to very inaccurate results. For example the iPhone 3G often returns positions with 500m accuracy, even if you pass the enableHighAccuracy:true. So watching the current position until it’s accuracy stabilizes is inevitable if you want to serve your user with pleasing results. Also this enables you to add some nice ‘wait for it’ animation that shows the current degree of accuracy – as for example seen in the iPhone Maps Application.

Luckily the Geolocation API also specifies the watchLocation function. This one can be called like that: var watch_id = navigator.geolocation.watchPosition(your_callback). This way your callback gets called everytime the users position or the accuracy of the current position changes. Under good conditions it just takes a few seconds to reach good enough accuracy for your application. As soon as your callback gets a position with good enough accuracy, you should call navigator.geolocation.clearWatch(watch_id) to disable the GPS again. This is especially important on mobile devices where an always on GPS can drain the battery quite fast.

To ease the usage of the geolocation api, i wrote a simple javascript that tries to get the current users location for a specific accuracy threshold. It is as always available on github.

Using it is really easy. Simply call simple_locator with your callbacks and you are done. Check out this quick example:


  var locator_update = function(coords, location_name) {
    var output = document.getElementById('output');
    output.innerHTML = 'lat: ' + coords.latitude +
                                      '; lng: ' + coords.longitude +
                                      '; acc: ' + coords.accuracy +
                                     '' + location_name;
  };
  simple_locator({
    threshold:50,
    running_callback : locator_update,
    finished_callback : locator_update,
  });

As an additional tool i also added reverse geocoding via google maps api v3. Just include the google maps api, set the google_geolocation:true option and the second parameter of your callback will contain the address of the current location. An example can be found in the simple_locator.html file on github.


HTML5 Flickr Visualization (iPad Test)

This post describes a little experiment using Flickr API, a webkit browser with support for CSS animations and transformations i.e. -webkit-animate and -webkit-transform and a little bit of jQuery that holds everything together. One important aspect is, that the developed animation should also run smoothly on mobile devices like the iPhone and the iPad.

The main idea is an endless stream of photos flying by the viewport using some nice CSS animations. So the perfect photosource seems to be the public Flickr stream. This brings us to step 1: Load Photos from Flickr.

Load Photos from Flickr

Collecting our photos is quite simple as Flickr offers their public streams in jsonp format – i.e. JSON Data passed to a Javascript function call. The Base url for all Flickr REST Methods is:

http://api.Flickr.com/services/rest/

The required parameter for this url is ‘method’, in our case we want to get the recent public photos so we use

method=Flickr.photos.getRecent

In addition to that we want some extra data (the url to the medium sized file, and the name of the flickr member posting the file) in our json stream. Therefore we set two additional parameters:

format=json&extras=url_m,owner_name

Last we want to pass a json callback so we can overcome ajax crossdomain restrictions. Luckily jquery helps us here and we only have to add

&jsoncallback=?

So the complete url to our Flickr stream should look something like this:

http://api.Flickr.com/services/rest/?method=Flickr.photos.getRecent&format=json&extras=url_m,geo,owner_name&jsoncallback=?

Combined with some jQuery code we can load all photos inside the json stream and put the photos in our animation queue (aka a simple javascript array):

Now that we finished the code to access our data source, we can create the basic HTML and CSS for our page.

Set up HTML and CSS

Next thing up we will define the stage on which our animation takes place. In essence we just need a container and some element to hold our photo. So the basic HTML structure looks something like this:

To make this structure look like a polaroid we simply reset the ul to no margin, padding and list type. The main style is attached to the li element using a white border, a nice dropshadow and a little bit rounded corners. In addition to that we offset the image just outside the top left corner of our viewport:

The div and small elements are just positioned at the top of the polaroid with a white background – nothing special there. Now our Polaroid should look something like this:

As a nice touch we can also add some gradient to the body background using for example:

background:-webkit-gradient(linear, 40% 0%, 24% 100%, from(#666666), to(#969696))

This finishes the basic CSS setup and we can go on to defining the animations needed.

Defining the animations needed

To animate the photos we first need to setup our viewport aka stage with some perspective – 800 seems to look quite nice – and in addition to that preserve the 3d style for child elements:

To animate the polaroid i choose three steps (can be combined into one, but i split it up just for clarity). First we want to move the photo from outside the stage to the center and add a little bit of life to this animation with some 3d rotation. This can easily be accomplished using @-webkit-animation – see the example below:

By using some additional keyframes at different points in time (25%, 75%) the pace and style of the animation can be alterated. To start the animation you just need to define an additional css class with the -webkit-animate property. As soon as this CSS class is added to an element, the animation starts:

The next two animation steps pop up the image to a larger size using the scale transformation. After a certain amount of time, the third animation simply drops the image out of the viewport:

Nothing more is needed to define the animations! Only one piece remains – a little bit of jquery code that defines the Application flow.

jQuery code

The last step is the code that binds together the bits and pieces. The workflow is quite Simple: on pageload we load the Flickr stream and fill our image queue. Then we start the animation cycle: We take the first image out of the queue and add it to our polaroid element. At the same Time we also start preloading the next image in the queue. Then we start the animation by first moving the image to the center, then popping it up, waiting a little bit, then dropping it out. As soon as the dropping out animation is finished, we reset out polaroids to its initial position and start all over again, gradually working down our image queue:

Note that i simply used javascript timers with setTimeout to reduce this examples lenght. It should of course be the preferred way to use the webkit animation events (webkitAnimationStart, webkitAnimationEnd) as described on Apples developer site.

With the flow described above we use just one html element that we animate all over again. Adding new elements for each photo would be possible too, but this can trigger a reflows that reduce performance. On mobile devices like the iPad this could result in long running applications fill up the available memory. This inevitably leads to a browser crash. To add a little bit more life to the effect it would always be possible to add some more elements and alterate between them.

The final Result

The final result looks something like the picture below, but of course it is better to view the live demo using a webkit based browser.


Mobile Safari Memory Usage and Images

Mobile Safari is known to quite often crash / terminate silently when loading certain Webpages. Since iOS 4, this happens frequently on older devices like the iPhone 3GS, but sometimes it also happens on newer Phones and the iPad.

The crashes are caused by mobile safari using up all available memory on the device, and as iOS 4 needs more memory for itself, it worsens the situation.

It is quite well known, that mobile safari does not like images that much. So the obvious solution is quite simple: reduce the amount of images on your page. This should be a standard procedure during the development of a useable mobile design anyway, but as Thomas Fuchs pointed out, advanced tricks like replacing gradient images with custom canvas elements can be beneficial too.

This solution is not possible for things like galleries or news sites with large images. In these cases ajax and dynamic loading of image content seems to be the best solution. In essence you load images as they start to move into the viewport and remove them as soon as they leave it – i.e. the user scrolls away. The simple way would be to just remove the image from the dom like in jquery:

$('.my-image').remove()

In our tests this however did not solve the problem, as constant loading and removing of images sooner or later overloaded the little mobile browser and lead to a crash. Still after a little bit of work on our side, we found a solution that seems to prevent memory growth quite effectively. The general idea is to reuse javascript Image objects to load inline image data – some sample code below:

This leads to a bit more work when implementing the frontend, but can quite effectively reduce memory usage and increase stability on mobile safari. We did not test this solutio on devices other than iPhone and iPad, but as mobile safari is webkit based, this solution should also improve pages on android devices. Though these are frequently equipped with much more memory anyway.

And last but not least: try to restrict your use of google web fonts or typekit fonts to a minimum, as loading more than one font weight / loading more than one font seems to crash mobile safari – more details on these problems can be found  on google code as well as the typekit blog.


iPhone Twitter Application Roundup

A nice List of all major Twitter Applications for the iPhone:
iPhone Twitter app roundup