Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.

  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint
Share this Page URL
Help

4. Hacking Your Graphics with Canvas and... > Hack 40. Use the HTML5 <canvas> Tag ...

Hack 40. Use the HTML5 <canvas> Tag to Create High-Res, Retina-Display-Ready Media

When Apple first introduced the Retina display on the iPhone 4, parts of the Web started to look pretty shabby. The display’s higher resolution made your quick-loading “web-ready” images look pixelated. In general, higher-resolution images mean longer load times. This hack uses the HTML5 <canvas> tag to provide Retina-ready imagery without the added weight.

There is a problem with our Retina screens. They look great (few people will debate that), but the way in which they accomplish this has caused a lot of problems for web developers. Apple first introduced the Retina display with the iPhone 4, in an attempt to solve two problems: create a display in which the pixels were indistinguishable to the naked eye, and not make iOS and Apple apps look like crap. To do this, Apple marked the pixel density much higher than was necessary, and in fact gave the display a density that was evenly divisible by the previous iPhone screen density. This enabled Apple to update all the visual assets of the iOS SDK and the iOS operating system to a higher resolution, and simply downsize it for older, less dense screens. For all the other assets in the Apple apps, the company used a method called pixel doubling to help the assets remain at the proper size.

Assets such as images and media on the Web fall prey to pixel doubling. This makes our web pages look pixelated and jagged. The common solution to this problem is to utilize images with twice the pixel resolution, which leaves us with images that are larger and web pages that take significantly longer to load.

In Comes the <canvas> Tag

The <canvas> tag is a drawing space for vector illustrations. Since the <canvas> tag is created using a set of definitions, the size of the illustration is inconsequential to the amount of data that is necessary to create it (unlike images that required the transfer of additional data to accommodate more pixels). This being the case, we can make our <canvas> tag Retina-ready without any additional page weight.

Let’s start by loading a simple example of a smiley face drawn out on a 200 × 200-point <canvas> tag. Here is the code for creating our example:

 var mySmile = document.getElementById('mySmile2')
    var smileCtx = mySmile.getContext('2d');

    smileCtx.beginPath();

    smileCtx.fillStyle = '#F1F42E';
    smileCtx.arc(100,100,99,0,Math.PI*2); // head

    smileCtx.stroke();
    smileCtx.fill();

    smileCtx.beginPath();
    smileCtx.moveTo(170,100);
    smileCtx.arc(100,100,70,0,Math.PI);   // Mouth
    smileCtx.stroke();

    smileCtx.beginPath();
    smileCtx.fillStyle = 'black';
    smileCtx.moveTo(60, 65);
    smileCtx.arc(60,65,12,0,Math.PI*2);  // Left eye
    smileCtx.fill();

    smileCtx.beginPath();
    smileCtx.moveTo(140,65);
    smileCtx.arc(140,65,12,0,Math.PI*2);  // Right eye
    smileCtx.fill();

Our smiley face looks great on a standard display, but it’s pretty jagged on the Retina display. Figure 4-12 shows how our canvas image looks on the iPhone 3Gs and the iPhone 4.

The canvas image displayed on the iPhone 3GS (left), and on the iPhone 4 with a Retina display (right)
Figure 4-12. The canvas image displayed on the iPhone 3GS (left), and on the iPhone 4 with a Retina display (right)

In order to have the illustration be smooth for the Retina display, we need to counteract the pixel doubling that is taking place. To accomplish this, we will add a few simple lines of code to our JavaScript:

    if(window.devicePixelRatio == 2) {
        mySmile.setAttribute('width', 400);
        mySmile.setAttribute('height', 400);
        smileCtx6.scale(2, 2);
        }

We will insert this into our code right after we declare our context, but before we start to apply our elements to the <canvas> tag. In essence, we have detected when pixel doubling is being applied (by checking the device pixel ratio) and then doubled the size of our <canvas> tag. These lines of code will result in the big, fat smiley face shown in Figure 4-13.

The smiley face twice the size it was before, thanks to the new JavaScript code
Figure 4-13. The smiley face twice the size it was before, thanks to the new JavaScript code

Now we need to rescale our <canvas> tag to fit our original page space. In order to have the page render all the pixels in half the size, we will set our canvas to 400 and then use CSS to shrink it back down to 200 px. Let’s add this CSS to the top of our page:

#mySmile{
    height: 200px;
    width: 200px;
}

With just a few lines of code we have essentially Retina-enabled our <canvas> tag without having to increase the page weight significantly. Let’s go back to our iPhone 3GS–iPhone 4 comparison to see our results (see Figure 4-14).

The canvas image displayed on the iPhone 3GS (left), and on the iPhone 4 with a Retina display after the addition of the new JavaScript code
Figure 4-14. The canvas image displayed on the iPhone 3GS (left), and on the iPhone 4 with a Retina display after the addition of the new JavaScript code

We’ve improved the experience for our Retina-display users without affecting the rest of our user base. You can apply this technique to any <canvas> tag, whether it is a page illustration or a canvas element used as a CSS background image. The only time you will not benefit from using this technique is when you import an image into your <canvas> tag that doesn’t support the Retina display’s higher resolution.

  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint