We Create Games

3d iPhone web apps

Posted June 18th by Jay Crossler in Code, iPhone, Maps, Web

For the third post in this series, I’ll be showing how to do some pretty advanced iPhone applications using Mobile Safari and HTML5. These should all work on the latest OS3 that came out today. What’s special about these is that they are not actual “Apps” that get loaded to your phone from the app store. They’re completely served through HTML and still have a ton of capabilities.

I got the idea to put the Flickr image results into a 3D “ring” from Antoine Quint, a developer for Apple Europe that I met at WWDC this year. These transform-3d talks were all the rage at the conference, and I plan to heavily use them in future projects.

You can see the application if you point your iPhone browser to http://wecreategames.com/apps/nearly2. Notice that if you look at this page in Firefox, it looks like gibberish (though it does ask for your permission to send geoLocation data). Even in Safari 4 on Snow Leopard, it doesn’t look exactly right, but it does give you GeoLocation and the ability to test through logs with the new excellent Web Inspector (you have to go into Preferences, and turn on Developer tools first). The apple guys assured me that a patch coming out for desktop Safari next week will fix these 3D rendering issues.

The code is available here (please note that some of it is reusing Apple’s example code. While my stuff is Creative Commons, please don’t tread on their copyright).

Speeding up page loads:

So, here are the important new parts of code:
<html manifest="default.manifest">

This tells the page to use a manifest, which is basically a document listing which files should/souldn’t be cached by the application. The application is just a text file that looks like:
CACHE MANIFEST
#ver0.03
CACHE:
index.html
square.html
style.css
script.js
data.js
ui/back_button_touched.png
ui/back_button.png
ui/back_button_touched.png
ui/back_button.png
gradient_bottom.png
ui/gradient_top.png
ui/play_button.png
ui/play_button_ring.png
apple-touch-startup-image.png
apple-touch-icon.png
NETWORK:
ws.php

This is telling the browser (mobile safari in this case) to download and cache all the files at the top of the list, and that the ws.php file shouldn’t be cached (as it will constantly be changing and returning different image results). This is really nice for iPhones, as large websites can be all cached on the first version, drastically speeding up the load time. I think that after 5mb, the user is prompted to see if the site is allowed to use more space. Also, there are a few weird things when using the manifests:

  1. When you update a file inside (such as data.js), the app won’t always notice. Instead, you have to physically change the .manifest file – I do this by changing the version # inside the file comment
  2. It takes 2refreshes of the app for the new manifest to take hold. This makes sense, as when a page is opened in the browser it will keep on loading. After it’s finished loading, it then looks for the new manifest information (so as not to slow things down). The next refresh then has the new manifest data
  3. You need to change your webserver’s mime type to return .manifest files as mime type of ‘text/cache-manifest’. Usually this is done through cPanel or whatever tool you’re using to manage your site.

Customizing the icon

On the iPhone, when users click the “+” button at the bottom of the screen, they can add the app to the home page. When they do, a screen shot of the app is created as the icon. With HTML5, you can specify which 57px x 57px icon you want to use with the code:
<link rel="apple-touch-icon" href="apple-touch-icon.png">

When the user adds the icon to the iPhone home page, the icon is given a glassy overlay. You can use ‘apple-touch-icon-precomposed’ if you don’t want the glass added.

Tailoring the page to look best on iPhone

The following css is in style.css:
body {
-webkit-touch-callout: none;
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);

On mobile safari, when you hold down on a link or piece of text for a few seconds, a callout pops up to ask if you want to copy/paste, or email. The first line disables this for everything in the document, which also helps with catching our custom touch events. Apple recommends a better practice is to only put these on certain objects on your page, not everything.

Mobile safari also tries to resize text to be helpful to users if it thinks the aspect ratio is too small. The second line turns off this adjustment.

The third line tells safari to highlight things in black if you click on them to show an action (rather than the default gray).

Making the 3D ring

The following code was all written by Antoine Quint, so I’ll only breiefly describe them.

In script.js, the code to calculate the rotation of the wheel and the position back in “Z” space is:
var angle = -i * (FULL_ROTATION / NUM_POSTERS);
item.style.webkitTransform = 'rotateX(' + angle + 'rad) translateZ(' + RADIUS + 'px)';

and in style.css, there are a ton of 3d-specific calls. Here are some important ones:
#ring-container {
/* make the perspective origin be the center of the screen */
-webkit-perspective-origin: 160px 208px;
/* set up the amount of perspective on the children of this container */
-webkit-perspective: 1000;
/* base transform for this container, need a value to transition from */
-webkit-transform: translateX(0);
}
#ring-aligner {
/* make sure the content lives in 3D space */
-webkit-transform-style: preserve-3d;
/* push back the content in the Z axis to cancel individual transforms set on ring items by script */
-webkit-transform: translateZ(-235px);
}
/* this matches all items within the ring */
#ring > li {
/* hide the back of the elements so that we don't see anything but the items currently in the front of the ring */
-webkit-backface-visibility: hidden;

The first call here is to add a “perspective” so that in 3d space, it looks like items are falling-back into the screen and getting smaller the farther away they are.

The last line applies to all list items with the #ring item. Because items are being rotated around in a circle, we turn off the back faces so that we don’t see them off in the distance.

-webkit-box-shadow: 0px 0px 3px rgba(255, 255, 255, 0.7);
-webkit-border-radius: 5px;

One of my favorite additions to HTML5 is how easy it is to add a shadow or rounded corners. Also, notice the 4th number above is the transparency – making it very easy to create blends.

Merging image lookups with the Ring

It can be a little painful debugging on your iPhone. The best tool I’ve found is to use Safari’s Web inspector, Firefox’s Firebug, or to just write messages out to the console. I’m also going to start playing with DashCode (on the mac), as it seems to have some nice debugging features. Instead of calling alert()s every time I want to output a variable, I use console.log(‘Error text’). Because Firefox doesn’t have this function, we add it:
if (!console){
var console = new Object();
console.log = function(intext){alert(intext);};
}

Most of the rest of the code was pretty easy to move over from the first example into the FingerTips example. One thing I quickly noticed was that as you walk around, new images are being pulled in to the array and it’s hard to know which ones to show. I’ll attack this more on the next post, but for now, a work-around is to just show the last images in the array:
var data_offset = 0;
if (data.length>NUM_POSTERS) {
data_offset = (data.length-NUM_POSTERS);
console.log('Data Offset is: '+data_offset);
}

How’s it look? I would love any feedback or suggestions!

(Back to last post in the series: FlickrProxy)
(Next post in the series: Full Offline iPhone apps with HTML Canvas and DBs)


7 comments to... “3d iPhone web apps”
Avatar
Tom

Hi, am just playing with manifest myself.

I have now tried to take things into one more hierarchy level, e.g.:

index.html

has a link to

FirstFolder/TheList.html

TheList.html has 10 links to documents in its FirstFolder.

All those ten links are properly typed in the manifest file. But only when I present them as direct links in the index.html do they show up.

Tapping a link to one of those ten documents from within TheList.html causes Safari to crash (only on the iPhone, all works fine on the mac).

Have you read anything to the effect that manifest cache only works for index page?

Cheers
Tom


Avatar
Jay Crossler

Tom,
I hadn’t tried that multi-hierarchy-linking within Manifest. Want to send me your code to see if I can reproduce it? If so, we can submit a bug report to the Mobile Safari team.


Avatar
Tom

Send me an email address. — BTW: Cool app.


[...] (Back to last post in the series: Nearly2, iPhone app with 3D transforms) [...]


Avatar
bernhard

Small tutorial for 3d CSS:

http://www.khtml.org/3dtut/


Avatar
Robin

hi,Jay.
i have a plobme in my offline app.
i created a manifest file already, and try to add a minitype to it by .htaccess file .

in this .htaccess file i write:
AddType text/cache-manifest .manifest

but it doesn’t work.

could you help me ? thanks a lot :)


Avatar
Jay Crossler

Robin,
The syntax looks right. Can you post your .manifest file (problem might be in there). Also, what other directives do you have in the .htaccess file? Any errors in the httpd log?




(required)



(required) (Won't be displayed)


Your Comment: