Canvas 2D Web Apps/iOS Web Apps

This chapter discusses the basic differences between HTML web apps for desktop browsers and web apps for iOS devices. It assumes that you are familiar with the previous chapter Getting Started with HTML Web Apps. If you haven't read that chapter yet, you should read it first.

Using Web Apps on iOS Devices

edit

In order to open a web app on an iOS device, you simply open the HTML file with the Safari web browser (or other browsers) on your iOS device. Thus, if you want to develop a web app for an iOS device, you should put the HTML file on the web such that you can access it with Safari. (If you don't have access to a web server, you can use services like the public folder of a dropbox account.)

If you try this with the example from the previous chapter Getting Started with HTML Web Apps (which you can access online), you might realize some differences:

  • You can change the orientation of an iOS device by tilting it and the web app will be rotated accordingly; however, the web app might then no longer fill the whole display because it uses an incorrect viewport.
  • On an iOS device, you can pan and zoom the web app with the default touch gestures, which makes sense for standard web pages but usually doesn't make much sense for web apps.
  • You can add a link to the web app to the home screen of the iOS device by tapping the share icon and then tapping “Add to Home Screen”. However, this link will just open the web app with Safari and therefore it won't work if your iOS device is not connected to the internet.

This chapter explains how to address these issues; i.e., it shows how to set the correct viewport size, how to handle orientation changes, how to disable the default touch gestures, and how to configure the web app such that users can download it to their device and use it offline like any other app (without indicating that it runs in Safari).

An example that integrates all these techniques is presented at the end of this chapter.

Setting the Viewport Size and Handling Orientation Changes

edit

In order to set the correct viewport size for a web app that is not supposed to be scaled or panned by the user, you should use this HTML meta tag right after the head tag:

<meta name="viewport" 
 content="width=device-width, initial-scale=1.0, user-scalable=no" >

This tells the Safari browser on iOS devices to always set the viewport to the full width of the device, disable scaling by the user, and start without scaling (i.e. a scale factor of 1.0). (Note that height should not be set to the device height since this can lead to problems.)

Orientation changes can be used to call an event function (similarly to onresize but using onorientationchange); however, orientation changes usually also result in resize events. Thus, it is sufficient to update the content of the canvas for the new width and height. If you want to render different contents for portrait and landscape orientation, you can check whether the width is larger than the height (landscape orientation) or the height is larger than the width (portrait orientation).

Apple developers can find more information about setting the viewport in Apple's Safari Web Content Guide under Configuring the Viewport. More information about handling orientation changes is available under Handling Events.

Disabling Default Mouse and Touch Gestures

edit

In order to disable all the default mouse and touch gestures, a custom event handler has to be defined in JavaScript:

      function ignoreEvent(event) {
        event.preventDefault();
      }

The line event.preventDefault(); disables the default behavior for the specific event. To call the event handler ignoreEvent for all mouse clicks and multitouch events, the following body tag can be used:

  <body bgcolor="#000000" onload="init()" onresize="update()"  
   style="-webkit-user-drag:none; -webkit-user-select:none; "
   onclick="ignoreEvent(event)" ontouchstart="ignoreEvent(event)" 
   ontouchmove="ignoreEvent(event)" ontouchend="ignoreEvent(event)"
   ontouchcancel="ignoreEvent(event)">

Additionally, this tag includes the attribute style="-webkit-user-drag:none; -webkit-user-select:none; " in order to disable any user interaction with HTML elements of the web app.

Apple developers can find more information about preventing the default behavior in Apple's Safari Web Content Guide under Handling Events.

Configuring Web Apps for Offline Use

edit

There are several ways to make web apps appear more similar to standard apps on iOS devices. These are:

  • customizing the icon on the user's home screen
  • customizing the startup image of the web app
  • hiding the Safari interface
  • changing the status bar appearance
  • specifying resources (in particular images) for offline use

Customizing the Icon on the User's Home Screen

edit

The icon should be a PNG file of exactly 57 × 57 pixels. If the file is located in the same directory as the HTML page and the name is filename.png then it could be specified this way:

  <link rel="apple-touch-icon" href="filename.png">

For Apple developers, more information is available in Apple's Safari Web Content Guide under Configuring Web Applications.

Customizing the Startup Image

edit

The startup image should be a PNG file of exactly 320 × 460 pixels in portrait orientation. If the filename is filename.png, it can be specified this way:

  <link rel="apple-touch-startup-image" href="filename.png">

More information for Apple developers is available under Configuring Web Applications.

Hiding the Safari Interface and Changing the Status Bar

edit

The Safari interface is hidden by a meta tag, which should be placed right after the head tag:

  <meta name="apple-mobile-web-app-capable" content="yes">

If this line has been added then the appearance of the status bar can also be changed; for example to black:

  <meta name="apple-mobile-web-app-status-bar-style" content="black">

Other options are default and black-translucent.

More information for Apple developers is available under Configuring Web Applications.

Specifying Resources for Offline Use

edit

In order to allow users to use a web app when they are not connected to the internet, you have to specify a manifest file that lists all the resource files (in particular images) that should be downloaded with the web app. (This does not include the manifest file itself nor the HTML file of the web app, nor the icon of the web app mentioned above nor the startup image.)

The manifest file is a plain text file with the filename extension .manifest and line breaks according to MacOS conventions. (On a MacOS X computer, you can use TextEdit to create such a file. On Windows, you can use editors that allow you to customize the character for line breaks, e.g. geany.) The first line has to be CACHE MANIFEST. The following lines have to include the filenames of the resource files (one name per line). If you get any of this wrong, the web app won't work without an internet connection but there won't be any error message. (Also note that the iOS device must be connected to the internet when the web app is started from the home screen for the first time.)

An example of a manifest file with name mywebapp.manifest that specifies two images could be:

CACHE MANIFEST
image1.jpg
image2.jpg

The manifest file itself has to be specified in the html tag of the web app:

  <html manifest="mywebapp.manifest">

For Apple developers, more information is available in Apple's Safari Web Content Guide under Storing Data on the Client. HTML5 specifies the related offline web applications. The Mozilla Developer Network offers a good introduction to using the application cache.

Complete Example

edit

In order to apply the presented techniques, you have to download all image files that your web app requires. For example, I downloaded a PNG image from Wikimedia Commons and called it HTML5_Shiny_Icon.png. Then, I created (with TextEdit on a Mac) a manifest file called ios_basic.manifest to specify the image file. The content of the manifest file is:

CACHE MANIFEST
HTML5_Shiny_Icon.png

The manifest file ios_basic.manifest is then specified in the html tag of the HTML file. Furthermore, I created a simple startup PNG image of 320×460 pixels with the name startup.png and an icon of 57×57 pixels with the name icon.png. Both these files are specifed by link tags in the HTML file. Note that the HTML file, the manifest file, and the image files are all in the same directory. The example is based on the example of the previous chapter Getting Started with HTML Web Apps but with the additions discussed in this chapter. (The full example with all files is available online.) The HTML file looks like this:

<!DOCTYPE HTML>
<html manifest="ios_basic.manifest">
  <head>
    <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
    <meta name="viewport" 
     content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="apple-touch-icon" href="icon.png">
    <link rel="apple-touch-startup-image" href="startup.png"> 
    <title>my web app</title>

    <script>
      var myImage = new Image();
 
      function init() {
        myImage.onload = update; // call update when image is loaded 
        myImage.src = "HTML5_Shiny_Icon.png";
      }
 
      function ignoreEvent(event) {
        event.preventDefault();
      } 

      function update() {
        // get canvas and context
        var myCanvas = document.getElementById("mycanvas");
        var myContext = myCanvas.getContext("2d");
 
        // set canvas size to window size
        myCanvas.width = window.innerWidth; 
        myCanvas.height = window.innerHeight;
        
        // clear context to transparent black
        myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
 
        // render in front-to-back order 
        myContext.globalCompositeOperation = "destination-over"; 
 
        // write some text in black
        myContext.fillStyle = "#000000"; 
        myContext.font = "bold 48px Helvetica, sans-serif"; 
        myContext.textAlign = "center";
        myContext.textBaseline = "middle";
        myContext.fillText("Hello, world!", 170, 60);
 
        // draw the image (behind the text)
        myContext.drawImage(myImage, 10, 20, 50, 51);
 
        // fill the background of the canvas with light blue
        myContext.fillStyle = "#C0C0FF"; 
        myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
      }
    </script>
  </head>
 
  <body bgcolor="#000000" onload="init()" onresize="update()"  
   style="-webkit-user-drag:none; -webkit-user-select:none; "
   onclick="ignoreEvent(event)" ontouchstart="ignoreEvent(event)" 
   ontouchmove="ignoreEvent(event)" ontouchend="ignoreEvent(event)"
   ontouchcancel="ignoreEvent(event)"> 
    <canvas width="400" height="300" id="mycanvas"
    style="position:absolute; left:0px; top:0px; "></canvas>
  </body>
</html>

The complete example is available online such that you can easily try it out. Note that there is also a title tag, which specifies the default name of the web app when you download it to an iOS device (via tapping the share icon). Once you have added the web app to the home screen of an iOS device, you should start it once with an active internet connection. After that you should be able to start it even if the iOS device is offline.

When you develop for Safari on an iOS device, remember to save files under new names after every edit and use the new files in order to make sure that Safari doesn't use a cached version (without your changes) of the files.


< Canvas 2D Web Apps

Unless stated otherwise, all example source code on this page is granted to the public domain.