August 3, 2010

Generating High-Resolution Graphics for iPhone 4 with HTML5’s Canvas Element

Update: If you’re also interested in targeting the Retina Display with high-resolution Apple Touch Icons, iOS 4.2 supports a method to do just that.


If you’re using HTML5’s canvas element to generate graphics for your mobile web app, it’s worth taking a moment to add support for high-resolution screens like the iPhone 4’s retina display.

The solution I arrived at was to take my existing drawing and conditionally scale it to twice its normal size, then set the width and height using CSS pixels. The result is an identical graphic, but without the jagged edges.

Here’s a quick demonstation based on one of the examples from MDC’s excellent Canvas tutorial. You can see in the first graphic below that the face renders fine on the iPhone 3, but on the iPhone 4 it’s being pixel-doubled, just like a static image, producing a jagged edge.

Before

With static images, the solution is to create a 2x version, and that’s the solution for Canvas elements as well. So begin by adding some conditional code to scale the image up 200%.

if(window.devicePixelRatio == 2) {
    canvas.setAttribute('width', 300);
    canvas.setAttribute('height', 300);
    ctx.scale(2, 2);
}

The scale method doubles the size of the canvas element. And, since a canvas image doesn’t have any “natural” dimensions, we need to adjust the width and height attributes. Finally, since these changes should only apply to high-resolution displays, window.devicePixelRatio lets us target that case.

Now we have all the pixels we need, but the iPhone 4 will still pixel-double the image until you set the width and height using CSS pixels.

canvas {
    border: 1px solid black;
    width: 150px;
    height: 150px;
}

Once that’s done, the scaled high-resolution version will render without jagged edges at the same “size” (in CSS pixels) as the normal-resolution version.

After

Here’s the code in full. (And here’s the original MDC example.)

I implemented this approach with the pageview graph in TypePad’s mobile web app, and I’m pretty happy with the results. There are lots of ways to use the Canvas element and CSS to generate high-resolution images, and I’m looking forward to seeing what others come up with.


See also: