Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2008-379
$eventId
ID of event: wwdc2008
$eventContentId
ID of session without event part: 379
$eventShortId
Shortened ID of event: wwdc08
$year
Year of session: 2008
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC08 • Session 379

Enhancing Your iPhone Web Application with CSS Transforms and Animations

Essentials • 1:07:16

Adding rich, hardware-accelerated graphics to your web content is now as easy as writing a few lines of CSS and JavaScript. Using the latest web standards, you can scale, rotate, or skew HTML elements, position page components within three-dimensional space, provide smooth transitions, and create captivating animations.

Speakers: Simon Fraser, Dean Jackson

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good afternoon, everyone. So I'm not Simon Fraser. My name is Gilles Drou. If you attended this Graphics and Media State of the Union on Monday afternoon, you know that we had a little technical glitch. And we really apologize for the inconvenience, and we're not able to show you a couple of demos. So I'm here with a little surprise. And I'd like to show you these demos right now.

So the first demo is called Fingertips. So it's a little application that enables you to browse through the fingertips movies that can find Apple.com. So what you see here is a simple layout, some video thumbnails on the left, a quick title and summary on the right side. And you can select a video and get a more precise summary.

Of course, in a browser, as you know, we have full control over and knowledge over the orientation. So here, in Safari on iPhone, you can reorient and relay out your page based on the orientation. It's very simple because it's done in CSS. You keep the same content. You change the layout.

And when we go back, the wheel is also relayed out accordingly. So here, to describe a little bit what you see, these are web elements mapped on top of a cylinder in 3D with CSS 3D transformations and GPU acceleration. And you can, with the flick of a finger, flick it like this. We are 60 frames per second. Again, can get very addicted. And I'm told we have a new fingertips video, so I'll select it and play it.

[Transcript missing]

If you want to see the rest of this video, feel free to go on PeterMizer.com. All right, so that's what I wanted to show you for this demo. Again, GPU-accelerated CSS transformations. The second demo-- so the team worked really hard on this project. And before they go on vacation, they decided to stretch the technology a little bit and do an application that-- build an application they could use around the globe to share their experiences with the rest of the team, the rest of us. And I'll go back. I'll tap. We'll call it Globetrotter.

And in this demo, I'll show you a couple of steps. I really want you to understand how it's been built, how it functions. So what you see here is a map of Earth. This image is mapped on top of a grid of elements, web page elements, and you can fly them in 3D with CSS3 Transformed because we have the power of GPU acceleration. And then you can map really nicely all these layers on top of a spherical structure and snap them to really fit and overlay on top of it a translucent image for lighting to give it a really realistic feel and immersive feel. And now you're ready.

Yes, you can. They worked really hard on that. Go for it. And again, this is totally interactive. So for instance, you can tap on the sphere and move it around. Go check out what's happening on the globe-- on the pole, sorry. Or with a flick of a finger, you can rotate it like this. We are at 28 frames per second. This is fast. And again, once you're done, give it a little time. And move it around. That also is very addictive, by the way. In resume, we're going to decline that one.

Let's check out-- oh, interesting. So Peter is in New York checking out the cube. I mean, he probably means the store on Fifth Avenue. So we can see he has photos and a video by the buttons on the bottom left. So let's check out his video. Hey, Gilles.

How are you doing? Sorry I can't be with you at WWDC this year, but I'm in New York City visiting family and friends. I have a big college reunion coming up, but the one thing I couldn't resist doing is seeing the great Apple Store here on Fifth Avenue. I hear there's a new iPhone. Check it out.

And when you're done, you can come back to the Earth view here. Let's check out the pictures that he has. So again, you can totally combine video and 3D and animated web page elements with GPU acceleration and CSS3 transforms. We're loading the pictures here. Oh, interesting picture, OK, from probably the inside of the cube. Let's see, really, if it got more than that.

Oh, I see. So apparently, Peter took a series of panoramic pictures. And so the way this has been built is simply by mapping on the surface of a cube six panoramic images. And so this is really pure six images. And you can flick it like this. We are 60 frames per second. You can check out the sky. What's going on down in the store, et cetera, et cetera. And again, when you're done, you can come back to the nearest view. And that is what I wanted to show you with these demos today.

So in this session, you'll hear all about the technology that's powering these demos, for instance. And so on this, I'd like to invite Simon Fraser on stage. Thanks, Gilles. Good job. So I'm the real Simon Fraser, not this guy. In case it wasn't clear from the demos, everything you just saw was done entirely in web content. There were no plugins. That was just HTML, CSS, and JavaScript. So in this session today, I'm going to tell you how you can use effects like those in your own web applications.

As you've already heard a couple of times at WWDC, we now have over 1,700 web applications written specifically for the iPhone. And I wanted to focus in on four of those and try and identify the types of things that you web developers in the audience have been trying to do with your web applications for the iPhone. The first one is the AOL TV listings. And this is using a JavaScript framework called IUI, which lets you build a hierarchical menu structure and also lets you do full-screen slides with a bit of a hack, scroll to, but it still is nice and smooth.

The second example is called csswalk.com, and it's a design directory of sites for mobiles and for iPhone. And it has this little animation that runs when you click on the orange tab. It's using the MuFX JavaScript library for that. That looked quite good on the screen here, but actually, in actual fact, it's pretty slow.

It gets about four frames a second. This next example is called iFlickr, and it gets photos from the Flickr sharing site. It uses IUI, again, and it has the slideshow. And you might expect that you'd get nice, smooth transitions between the pictures and the slideshow, but actually, it doesn't. The pictures just change.

Finally, we have a game. This is called Gravity. And like many games on the iPhone, this is using JavaScript to animate elements in the page. And again, it's not getting really good frame rates. So we can see from these examples that you guys who've been trying to write web content for the iPhone with animations in, you found it pretty hard. It's a pain to write JavaScript for animations. You either have to do a lot of timing-based code yourself, or you have to suck in some of the JavaScript libraries like Scriptacular or some UFX or something. And that's just a pain to manage all that code.

Secondly, once you've actually started trying to do animations, you probably find that they're too slow. They're not really giving you the performance you want. And that means that because your animations aren't fluid, they don't really fit into the web content. They seem kind of out of place. You're not getting a native feel to your web content.

So today, I'm going to talk about some new functions in Safari on iPhone 2.0 that make all this a lot easier for you. You can get rid of all this old JavaScript code that you had and replace it with just a few lines of CSS. It really is that easy. Also, on iPhones, some of these transitions and animations are hardware-accelerated, so you'll get really great performance.

And once you start putting this together with some of the new features on Safari on iPhone, like touch events, you can generate some really cool types of content. And let me show you a few examples that we're going to be looking at in today's session and telling you how to build.

This first one is a little slide show that we built up, a little photo album. And we'll do a demo of that later. But it has a nice, smooth transition between different sorting orders that you saw there. This second example is something that tries to emulate the native menus on the iPhone. And it has nice smooth slides and the blue highlights, so it feels really nice.

This third one shows you that you can do 3D transforms in web content now. We have something like a widget flip. And then finally, the one you just saw, which is our fingertips browser. And I'll be talking in a bit more detail about how we built this later in the session.

So just really press home here. Everything is in web content that we're doing here. We've added a bunch of new CSS properties to Safari on iPhone 2.0. And those are properties-- and we think that CSS is really the best place for these kinds of new functions. CSS cascading style sheets allows you to separate the presentation of your content or presentation of your document from the content. And transitions and transforms and animations are very much presentational qualities. You should be able to load in a new style sheet and get an entirely new set of transitions and animations in your page.

Another nice property of CSS is that older browsers will just ignore those new properties, so you can write content that degrades gracefully in other browsers. And finally, Most of you are probably familiar with web development, and this is just still web development. We're not adding any new technologies that you have to learn. So it's a very small, incremental amount of learning for you.

I said most of it's in CSS. There are a few small amounts of new API. There are some DOM events for animations. We'll talk about those later. And we also have some new JavaScript APIs related to some of the 3D transforms. But really, it's just web development. If you already know HTML, CSS, and JavaScript, this is going to be really easy for you to pick up and get running right away.

So as I mentioned, everything is in Safari on iPhone 2.0. Apple is committed to open standards, and all the properties that I'm talking about today are included in some draft proposals that we've submitted to the CSS working group of the W3C. And we hope that those will be included in CSS3. You can read our proposals online at webkit.org/specs. And because they are still draft properties, they do have a -webkit prefix. So you'll see -webkit quite a lot in our examples today.

So let's summarize what we'll cover in today's session. You may already have been to some of the WebKit sessions where they've told you about 2D transforms and transitions. So we're going to go over that fairly quickly. We'll just have a refresher. And then we'll get to the meat of the presentation, which is keyframe animations and then 3D transforms.

And then finally, we'll talk about how to bring some of this stuff together with some of the other features on the phone, like touch events, and then talk about how to get the best performance out out of the phone when you're doing this stuff. So I'd like to start by inviting Dean onto the stage, and he's going to show us a demo using 2D transforms and transitions.

Thanks, Simon. My name's Dean. Now, Simon, can we switch to the phone, please? So Simon didn't tell you he's actually an entomologist by training, and he likes taking photos of bugs, these type of bugs at least. You'll also notice I'm pretty sure he didn't use any Flash on this.

So behind the scenes, at the moment, he's arranged the photos in the order in which they were taken, but let's suppose he's also picked favorites. So I can click a button down the bottom here, and it resorted the photos into favorite order, and I can switch back. Now, this is something that's really common, is not showing anything new here.

But suppose he wanted a more organic feel to his website. So let's apply a random rotation to some of the photos. And you can see here we've laid out the images in a sort of more natural feel, as if they've been thrown down on a table. Now, this is something you wouldn't have been able to do previously without either going back to the server and getting the server to generate a new image and sending it back down, or using something like Canvas. But in this case, we've applied transformations that are hardware-accelerated. So you can see I can tap this, getting really quick response, because the compositing is done in hardware.

Now, the iPhone, as Simon mentioned, we've got touch and gesture events here. So let's say I want to reorder these photos or arrange them in a particular way. I just tap on the photo. I can move it around. Again, you can see you're getting really great performance here.

But let's suppose I want to zoom in. So I can attach a JavaScript event listener to the pinch event or the rotate event. And here, I can resize them or rotate them. Again, great performance. So once you have this great performance, maybe you want to go a little bit further. Oops.

Now here we've got the same demo again. The photos are sorted in date order. But suppose I -- rather than just snap to the final value, I want to have an animation as I move to the new sorting. So in this case with JavaScript, when I click on the favorite button, I just tell the browser which order I want the photos in, and it's the web browser that does the animation. It's the one that calculates all the little intermediate steps and moves the photos to the final position.

Again, it's really easy. I'm just setting the final state. The browser knows what the current state is and does everything else. And you can do this between any state. So as I go to the rotated view, you can see I didn't have to do anything special just because the photos have a transform on it.

Now, with these transforms, they're really powerful. You do some amazing effects, and Keynote is a great example of some effects. So here we go. I just start an animation here. And all I'm doing here is setting a slideshow that says, you know, every second over time, it says, move this current photo into view. And when I'm done with the slideshow, I can just tap, and it'll transition back to the final state.

So, thanks. Now, the really important thing to learn here is that these two demos, the first demo and the second demo, were identical except for two lines of CSS. I actually got that animation and those transitions by adding just two lines to the CSS. And I'm going to invite Simon back, and he's going to show you exactly what those two lines are. Go back to slides, please.

OK, so this is the demo you just saw. And we're going to look at 2D transforms and transitions by pulling apart this demo to see the really important bits, to see what made it really tick. So CSS 2D Transforms. You've probably heard about these already in the context of some of the WebKit sessions.

So there's a new property called WebKit Transform. And that allows you to change the rendering location of something on the page. And 2D Transforms, of course, just let you do affine transforms. Things like translate, rotate, scale, and skew. And you're probably familiar with those from SVG, or even maybe Core Graphics if you've done some native coding.

And you can also control the origin of the transform with WebKit Transform Origin. And that's actually quite useful. And we'll see that later in the session. So a very simple example here, we've got a div on our web page which we've given a class name called box. That means we can style it with a dot box selector. And now we're just going to add a transform. In this case, we're using a translate of 400 pixels in x and 200 pixels in y. And that's going to cause the box just to render in that new location with that offset.

We used pixel values there. You can also use percentages and other CSS lengths. So we can translate by 150%, and that's going to move it by 1 and 1/2 times its width. And then we can also translate by other m values, which is going to push it down by four times the line height.

Rotations are very similar. We can apply a rotate transform. In this case, we're using degrees, but you can also use grads and radians. You can also concatenate these transforms together to form compound transforms. So here, we're doing a rotate followed by a scale, and those get applied in the order in which you expect. So I mentioned transform origin. And by default, the origin of the transform is in the center of the border box. So the default value is 50%, 50%. You can see the red dot here, which represents the origin. And we can move that.

to, say, the top left corner by using those keywords, top left. And now if we rotate the box, it's going to rotate about that corner. Here's another simple example. We'll put it on the middle of the right-hand side. The box is 200 pixels wide. And again, that's going to be the origin of our rotation.

So let's go back to the demo we saw and look at the HTML and JavaScript to see how we laid out these images. So because we have a bunch of images here, we don't want to write fixed CSS for these. We're going to position things using JavaScript. And it's very simple. We simply loop through the photographs.

We compute an x and a y position based on the location of the picture in the grid. And then we're building up a translate string, just using string concatenation in JavaScript. It's very simple. And we're assigning that to style.webkit-transform. And that's setting the inline style on the element. You'll notice that in CSS, we use dash webkit dash transform. And here, that became camel case. It became webkit capital T transform. And that's a standard conversion that happens when you're accessing CSS properties from JavaScript.

Now, the random view that we saw, the light table view, is almost as simple. In this case, we can compute an x and a y position at random, and we can also compute an angle. And then we're building a compound transform, which is a translate followed by a rotate, and assigning to WebKit transform.

So let me just summarize 2D transforms very quickly. The property is WebKit Transform, and there are various values like translate, rotate, scale, and skew. And these are going to give you affine transforms. And if you need to, you can control the origin of the transform with WebKit Transform Origin.

Now, a couple of things to note when you start transforming elements. The first is they make an element positioned. That means that if the element doesn't already have position, like position absolute or position relative, it will behave as if it had position relative. And that can change the positioning of some of its child elements if those child elements use positioning.

And the second thing for the CSS gurus in the audience is that transforms create stacking context. That means that the element is going to behave as if it had an explicit z-index, and that may change the front-to-back ordering of some other elements on the web page that also use z-index. And CSS 2D Transforms are available on the desktop in Safari 3.1 and also now in Safari on iPhone 2.0.

So transitions now. And we saw transitions working in the demo. They allowed Dean to show the nice, smooth animations between the different states. So transitions are these automatic animations that you get when CSS property values change. You can think of them as implicit animations. Essentially, what's happening is when the value of a CSS property changes, the engine is doing this interpolation kind of under the hood over some period of time.

And transitions are going to run whenever the values of the properties change. So if you change a value through maybe setting inline style or setting a class attribute, which then brings in some new style rules, or maybe on active style, you know, for a clickable element, then you will get transitions.

And you set up the transitions and control them with various properties, which we'll see. You can control which CSS properties are going to undergo transitions and how long the transitions take, how they move-- in other words, an acceleration curve or timing function. And you can also set a delay before the start of the transition.

So let's go back to our box example here. Same box, but we set up a couple of style rules that specify that WebKit Transform is going to transition. And it's going to take two seconds to do that. And now when the transform changes, we'll get a nice, smooth animation from the old state to the new state. And we didn't have to do any extra work to make that animation take place.

Let's go back to our example. And Dean said when he demoed it, this was just two lines of CSS to have these really cool, smooth transitions between the sort orders. And these are those lines of CSS. We're setting WebKit transition property to WebKit transform. And we're specifying that the transition is going to take half a second. And that's all it was. And those styles are being set on the photo elements on each picture there.

I mentioned you can control the acceleration curve. Technically, that's known as the timing function of the transition. And there are a number of built-in timing functions. The property is WebKitTransitionTimingFunction. And the built-in curves that you can get are the following. There's ease, and this gives you a nice, smooth, organic animation that kind of starts slowly and speeds up and then slows down. There's linear, which is constant velocity. Ease in, which has a smooth start and then speeds up. Ease out, which starts quickly and then slows down. And then ease in, which is slow at both ends and fast in the middle.

And if you want to get really fancy, you can specify your own timing function with the cubic Bezier function. And here, what you're doing is you're specifying the two control points of a Bezier curve, the orange line in the picture. And you can imagine, just like Bezier programs like Illustrator or something, you're controlling how that curve is moving by the control points.

So quickly, let's summarize CSS transitions. They're these automatic animations that you get really for free just by setting them up. And you can control which CSS properties are going to undergo transitions with WebKit transition property. Now, the default value for WebKit transition property is all, which means that the engine will try to animate as many things as it knows about or it can animate. On the phone, that's not always a good idea, because you really want to restrict animations to the things that your users are going to see. And so it's a good idea to set a specific WebKit transition property just for the things you want to undergo transitions.

Then you can control how long the transition takes with WebKit transition duration, and how it moves with WebKit transition timing function that we just saw. And finally, something we didn't use in the demos, but is often very useful, is a delay before the start of the transition. And this allows you to do fairly complex builds where maybe you set a class attribute on some container element, and then you can have the children of that element flow in one by one by using WebKit transition delay. So that's quite a nice kind of feature that can give you some really nice cinematic qualities to your transitions. And transitions, just like 2D transforms, are available in Safari on the desktop, in Safari 3.1, and also Safari on iPhone 2.0 now.

So we've just talked about transitions, which are these automatic, kind of implicit animations. Often you want to do a richer, more controllable animation. You want to have something maybe that repeats a bunch of times, or that you can start and stop explicitly. And you can think of this as something like the dock bounce in Mac OS X. You want to tell something to start bouncing and then tell it to stop bouncing.

And you can't easily do that with transitions, so we've added something else, which is keyframe animations, again described in CSS. And I'd like to invite Dean back on the stage. And Dean's going to show us an old version of a website that he has for some side business that he runs. And then that used JavaScript. And then he's going to show us the new version, which is taken to the next level with keyframe animations. Thanks, Dean. DEAN JOHN MANNING: Thanks, Simon.

So working at Apple is really awesome, but like most programmers, what I really want to do is be a landscape gardener. So, of course, who wants to be a run-of-the-mill landscape gardener when I can be a Web 2.0 landscape gardener? So I thought, I'm going to have a website. And I'm not just going to have any website. I want a little bit of oomph to it.

And so I might add some animation. In this case, I've got using JavaScript to animate some leaves. Now, what's actually on the screen there is about 30 leaves, randomly chosen, and a JavaScript timer that's running as fast as it possibly can to move the leaves a little increment down the page.

And when they get to the bottom, as they fall off the bottom of the page, they snap back to the top and start falling again. Now, there's a few things you'll notice here. One is you're getting, you know, basically you can see each step, and the animation isn't really smooth at all. Also, there's a fair bit of code behind this. And, well, you know, it really just doesn't look so fantastic.

My landscape business isn't going to take off enough for me to give up my programming job. So let's reimplement it using CSS animations. So right away, you'll notice when they come on stage, you've got this incredible improvement in performance. There's no longer any jerks, and everyone hates jerks.

We've gone from about between six and eight frames per second to about between over 40 frames a second, so really impressive performance improvement. And that's because, again, we're using the hardware acceleration on the phone to speed things up. Another thing you might notice is there's a few differences from the previous animation. First is, rather than the leaves falling straight down, they've got a slight little rotation to them to make them look a little bit more like the way a leaf would typically fall.

Now, so again, at 40 frames a second, we're rotating 30 images in this case. Again, something you couldn't possibly do if you were just using JavaScript. Again, it's the hardware acceleration that's doing that. Secondly, you might notice that rather than just dropping directly off the bottom of the screen, as they get towards the bottom, they fade out very, very slightly.

Now, it's important to describe what this does to you. The first thing is, you know, you're getting this incredible performance improvement, but secondly, you also don't have a busy loop in JavaScript that's chewing up the CPU, moving all the images. You've just set the properties once and the animations are happening.

Secondly, we've moved from about 100 lines of JavaScript into about 10 lines of CSS. So that's fantastic for two reasons. One is there's less code to maintain. Secondly, it's a declarative format rather than a programming format. So again, it's, again, more easy to maintain. And also, someone that's not a JavaScript expert that's a web designer, say, just knows CSS, can start putting these animations into websites without having to learn JavaScript. So that's the demo. Again, like the last time, Simon's going to come back and show you how we built it and how to get it working on your own sites. Thank you.

OK, so let's learn about CSS keyframe animations by pulling this demo apart and looking at the various animations we have in there. First of all, let's talk a little bit about how to set up animations. So CSS keyframe animations are a little more complex than transitions, simply because you have more control over the way the animation is going to move. The first thing you need to do is to describe the keyframes for the animation. And we've added a new @ rule to CSS, and you'll see that in a moment.

Secondly, you need to apply that set of keyframes to an element. And then you have a bunch of properties that allow you to control the behavior of the animation, how long it takes, how many times it repeats, and so on. And we'll see those as we go on.

CSS animations, keyframe animations are only available right now in Safari on iPhone 2.0. So Dean just showed us this. Let's start pulling it apart. First of all, I'm just going to show you some markup and some JavaScript to show that this is real. This is not fake. We've got two divs in our web page. The first one is just a container. And we're going to add leaves dynamically to that through JavaScript. Again, just because it's repetitive stuff, and we don't want to have to manly code all those boring lines of HTML.

So here's the JavaScript that sets up the leaves. It's just going to run on page load. And it's using standard DOM APIs to find the leaf container element with getElementById, and then run through a loop, create a leaf, and then append the leaf to that container. And creating the leaf is, again, just normal, standard JavaScript-making, calling DOM APIs.

If you're actually generating content on the fly, please do use the DOM APIs. Don't use document.write. That's evil, and you should never use it. It's very inefficient. So standard stuff here. We're going to create a div, and we're going to give it a class name of leaf, so we can style it in CSS.

And then we create an image element, and we assign an image URL at random from some four or five images that we have. And we append that image element to its leaf container. And you'll see a bit later on why we have this structure of a div with an image inside of it.

So the first animation there is the major animation, which is going to move the leaf from the top of the screen to the bottom of the screen. So that's the fall animation. And as I mentioned, the first thing we do when we're setting up an animation is to describe that animation as a set of key frames.

So this is the @ rule that I mentioned. And because it's in draft form, it has a WebKit prefix. So it's @-webkit-keyframes. And then we give the set of key frames a name so we can identify it. And that name can be anything you like. So we're using fall in this case.

Inside of the keyframes are the actual keyframes themselves. And we've got two here. We've got an initial state, which is the from keyframe, and then the target state, the to keyframe. And within those keyframes are the actual style rules that we want to animate. In this case, we're going to animate WebKit Transform.

And so our initial state is going to be a translate in Y of minus 50 pixels. So that starts the leaf off above the top of the screen. And then a final state is positive 600 pixels. So that's going to move the leaf down below the bottom of the screen.

So we've described our keyframes. Now we need to actually apply those keyframes to the leaf elements. And we do that using the following style rules. We've set WebKitAnimationName to 4, which is the name of the keyframes. And we're going to use a duration of 10 seconds. So our leaves will take 10 seconds to progress from the top of the screen to the bottom of the screen.

And then we want the leaves to keep going for as long as the page is loaded. So we're using an animation iteration count of infinite. You can, of course, use numbers like three and four. But we want to use the keyword infinite, so they just keep going. And then we want our leaves to progress from the top to the bottom at a constant velocity. So we're using the linear WebKit animation timing function. So let's actually see what this animation looks like now. So it's just a constant velocity move from the top to the bottom. When it gets to the bottom, it's going to snap back to the top and start again.

Very straightforward at this point. Now, you'll notice when the leaf got to the end, it just snapped out and then reappeared back at the top. We want that to be a little more organic, so we've added another animation we're calling the fade animation. What that's going to do is it's going to fade out the leaf towards the end of its travel.

So we have another set of keyframes. This time we're naming them Fade. And these are going to animate the opacity property. And we're using three keyframes here. We have an initial keyframe at 0%. You can either use from or 0%. That's anonymous. And opacity is 1 in the initial state.

And then at 75%, we have another keyframe with opacity 1. And then at 100%, or the two state, we're going to animate to opacity 0. So that means for 3/4 of its travel, the leaf is going to still have opacity 1. And then between that 75% point and the 100% point, the leaf is going to animate to opacity 0.

And just as before, we apply that animation to the leaf divs-- .leaf is the container div, by the way-- using the WebKitAnimationName property. So now we have two animations running on our leaf divs. We have the fall one and the fade one. And we can use comma-separated values in the CSS to concatenate the animations together.

They both have a duration of 10 seconds. And that's actually why we set up the keyframes this way. We want these animations to be synchronized. We want the progression down the screen to synchronize with the opacity phase, so the opacity phase always starts at that 75% point. And so we've set them both to iterate an infinite number of times and both have the same duration. And those animations will actually stay frame synchronized for as long as they run while the page is loaded.

Now, we used linear for the timing function on the fall. We're going to use ease in for the timing function on the opacity, because at that 75% point, we don't want opacity to just kind of snap in sharply. We want it to have a nice, smooth start to the animation. So we've used eased in there. So let's run this animation and see what it looks like.

So the full animation, of course, is pushing the leaf down. Now at the 75% point, just about here, you see the leaf starts to fade out. And then it's going to snap back to opacity 1, reappear at the top, and then repeat. So here's the opacity fade right there. So that's pretty close to what Dean showed you in the demo, but he mentioned his leaves had this very organic kind of side-to-side motion, like they were being blown around in the wind. And that was achieved with another animation called the swing animation.

And this is, again, animating WebKit Transform. And it just has two keyframes. It's very simple. And the initial keyframe is a rotate of minus 30 degrees, one way. And then a final keyframe is a rotate of positive 30 degrees. So that's going to cause our leaf to rotate back and forth like this. So let's apply that. And you'll notice that our selector here has .leaf and then is targeting the images, which are direct children of the leaf divs. So this animation is applying not to the leaf div, but to the image inside of it.

We're using a duration of three seconds now, which means that this animation will run faster than the previous two. We still want it to go an infinite number of times. But now there's something else we want it to do. Instead of running forward and then snapping back and running forward again, we want it to run forward and then go backwards and then forwards again. And the way we do that is with a new property called WebKitAnimationDirection.

And this has two values, normal and alternate. And so alternate is the one we want here. And because we have this back and forward motion, we're also using a timing function of ease in/out, which if you remember is slow at the start and end and fast in the middle. So that'll give us a nice symmetrical animation when we run it backwards and forwards.

Now, the final trick here is the use of WebKit Transform Origin. If you remember, we can use this to change the origin of the transform. And what we're doing here is we're using that so that instead of the leaf rotating in place, the leaf is actually going to rotate about a point which is above the top of the leaf div. And so the leaf is going to move like this. And let's run that, and you'll see that.

We've got some debugging boxes here. The leaf div has an orange border on it. And then we've got a red dot for the origin of the transform. So now, by combining those three transforms, we have a rich, kind of organic feel to the movement of our leaf on the page.

One thing that we didn't need in this particular demo, but often you will want to do when you're writing animation-rich content, is you might want to know from JavaScript when your animations start, when they loop, or when they get to the end. So we've added some DOM events for you. These are called WebKitAnimationStart, WebKitAnimationIteration, and WebKitAnimationEnd. And you can listen for these in the standard way that you listen for DOM events. You can either use HTML attributes here.

Or more commonly, you can use something like addEventListener. Please use addEventListener in JavaScript. Listening for WebKit animation end. And in this case, we've got a handler function. One thing that you can do on the animation events is they have a couple of properties that are useful. One of those is animationName. So this lets you tell which particular set of keyframes caused this event to fire.

Now, animations are a little different from transitions because they're very explicit. You decide as the author when they're going to run. And so I should explain how they actually get applied. So an animation will run if WebKit animation name specifies a known set of keyframes-- in other words, the keyframes that are in the CSS files that are loaded-- and if there's a duration that's greater than zero.

And once an animation is running, the properties or the values of the properties in the keyframes will trump all other style rules. So they'll override inline style or important rules, basically everything. And then once the animation gets to the end, the effects of that animation disappear entirely. So the element will revert to its non-animated appearance.

Now, having animations trump all other style rules might be problematic in some cases, depending on how your CSS is structured. So if you want to disable animations for an element, you can do that by setting the WebKitAnimationName property to none. And that will override previous values for WebKitAnimationName.

So let's summarize CSS keyframe animations. These are explicit keyframe animations that give you rich, controllable animations in CSS. There are two things you need to do to set up animations. The first one is to define the set of keyframes, which you give a name to. And then the second one is to actually apply that set of keyframes using WebKit animation name. You control how long the animation takes with WebKit animation duration and the iteration count. Now, WebKit animation duration is the duration of a single cycle of the animation. So the total time that it's animating is going to be the product of the duration and the iteration count.

And then you can control how the animation runs with the timing function and the direction. We saw the direction in the leaves demo. You can say normal or alternate, and alternate gives you that back and forward direction. And then the timing function-- I should just take a moment to explain.

If you remember from transitions, the timing function affected the acceleration curve over the entire transition. With keyframe animations, it's a little different. You're telling us what the keyframes are. So we expect that you've already kind of built a basic timing function into your keyframes. But WebKit animation timing function allows you to do interpolation within those keyframes.

And this means that you can build nice, smooth, fairly complex animations just by specifying a few keyframes and then perhaps using some custom Bezier curve timing functions within those keyframes. Just like transitions, you can set a delay before the start of the animations. And then, as I mentioned, we have some DOM events. And CSS keyframe animations are only available in Safari on iPhone 2.0.

OK, so we talked about 2D transforms earlier. And you saw those. You've seen those on desktop. You saw them in the demo here. We've now added the ability to describe 3D transforms in CSS. This is pretty exciting stuff. We think this is very new and exciting. And we've kept it as simple as we can.

So 3D transforms are really just an extension of two-dimensional transforms. So they're using the same dash web git dash transform property that are used for 2D transforms. However, when you start building three-dimensional content, you need to make it look 3D. And that involves applying some perspective. So we have some star rolls that let you control perspective.

And then, since we can do 3D, well, we want to build sort of 3D hierarchies of objects and maybe have articulations and things for animations. So we have to control some of the flattening that HTML is going to do by default. So we have some rules for that.

And then 3D transforms are also kind of weird, because you can actually transform an element all the way around and start looking at the back face of that element. Sometimes you don't want that, so you can control that as well. And 3D transforms are only available in Safari on iPhone 2.0.

So I'm going to explain 3D transforms by running through an example of how we build up this. And this is a three-dimensional ring that we've built up. The orange boxes we're calling posters in the example. You'll see that in a moment. So let's see how we put this thing together. Again, we have some basic markup. In this case, it's just a couple of divs. We've got a container div and then a div called ring. And ring is going to be the parent of the actual elements that you saw rotating around the orange boxes.

And just as before, because we have a number of repetitive elements, we don't want to code all those in our HTML, so we run a JavaScript loop that that does a create element for each div. It's going to give it a class name of poster so we can style it. And then it's going to append it to the ring element. Standard DOM APIs.

And we have some standard CSS just to give our ring a size. The container has height and width set on it. The ring, we're going to give position relative, and you'll see why in a moment. And again, we give it some explicit height and width. And then the poster elements, we want to be able to position those inside the ring. So they're going to have position absolute. And that's why we gave the ring position relative, because then the ring is going to act as basically the origin of that position absolute. And the posters have height and width.

So here's what our ring looks like. We've given it a green border in CSS, just so you can see where it is. And those of you who are familiar with debugging complex CSS layouts will know that it's very useful to set border style or outline style so you can see where all the boxes are. And that's also true in 3D.

So we run one loop of our JavaScript here. We've made a poster element. We've put it in the parent, which is the ring. And it's appeared in its default location in the top left corner. Often when you're doing 3D transforms and you're moving elements around, the transform origin, as I said before, defaults to the center of the element.

And we're building this ring, this three-dimensional ring, and we want the center of the ring to coincide with the center of that parent element. And so the best way for us to position the children is to start them off at that center position. So we're going to use standard CSS positioning. We're going to set a left on the posters, just so they start off in the middle of the ring element.

And now we get to the good stuff. Now we're going to start applying some 3D transforms. So the first one we do is we're going to use an angle to spread the posters out around the ring. And we're just going to compute those angles in JavaScript. You'll see that in a minute. We've just got a static one in CSS so you can see what it looks like. So this is one of the new values for WebKit Transform, and it's rotateY. So just rotating in Y by minus 30 degrees.

The second step is to move those posters from the center, where they are, out to the periphery of the ring. And we've done that with a compound transform, which is exactly the same as-- or behaves in the same way that you saw for 2D transforms. We've got the rotateY, followed by the translate.

And the translate here is in Z. Now, translateZ is a new 3D transform, and it lets you transform something in and out of the screen. A negative translate in Z is away from the viewer, or kind of behind the screen, and a positive translate is towards the viewer.

So let's take a moment to look in more detail at 3D transforms. The property, as I mentioned, is the existing WebKit transform property. But there are some new values that describe three-dimensional transforms. The simplest is translate3D. So that enables you to describe a translation in x and y, and also in z now. And then there's a convenience function, translatez, which just does a z translation. And the values here are the same CSS lengths that you saw for 2D transforms.

Now that we have 3D, we can rotate around the different axes. So we have rotateX. X is the horizontal axis. So an X rotation will be rotating an object this way. And then we have rotateY. The Y axis is the vertical axis. And so a Y rotation will be rotating something this way. And then just for consistency with 2D transforms, we have rotateZ. And the Z axis is in and out of the screen. So rotateZ ends up just being the same rotation as a 2D transform.

If you want to do a really fancy rotate, you can rotate about an arbitrary vector. So there's rotate3D, and that takes four arguments. It takes an x, y, and z position and an angle. And what this is doing is this rotates about a vector between the origin and that x, y, z point. And then the angle is the amount of rotation there. And the angle units are degrees, radians, and grads, just like for 2D transforms.

And finally, those of you who are familiar with 3D math in native code maybe, or maybe using 3D packages, will know that 3D transforms are usually described as mathematical matrices, as 4 by 4 matrices. And so if you want to specify a full transform as a 4 by 4 matrix, you can do that using the matrix 3D value here. So this takes 16 numbers, and those numbers are the contents of the 4 by 4 matrix, a homogeneous matrix, in column major order.

So let's go back to our example. We positioned one poster just by using CSS, but we're actually going to run our JavaScript loop and position the posters incrementally as we build them. So here you see-- it's a bit near the bottom of the screen. I apologize for that. But we're building a compound transform, which is a combination of that rotate around the y-axis, and then the translate z, which pushes us out from the origin of the ring.

So now we've built our three-dimensional ring, It looks pretty good. The next thing we'd like to do-- You'll stop clapping when you see this next bit. So the next thing we'd like to do is we want to rotate that ring, because that's the whole point, right? We want this nice ring that maybe we can move around with touch events or something. So to rotate the ring, again, we use 3D transforms. We're going to stick a Y rotation on the ring element, which is the green box. Let's do that. And well, actually, that doesn't look very three-dimensional. That looks kind of flat. Oh, well.

Until today, HTML was a 2D medium. It had no concept of 3D. And so when you start describing 3D transforms, you need to somehow get around this problem of HTML being 2D. So the way we've done that is to add a new property called WebKitTransformStyle. And this has two values, flat, which is the default, and then preserve3D, which is the one we want. And what preserve3D does is it avoids flattening.

What will happen by default, even if you give an element a 3D transform, is it'll be rendered with that transform, but it'll be rendered into its parent element. So it'll get flattened. It'll look 3D from the front, but if you turn that parent to the side, you'd see it was still just on the plane, as we saw. What we'd really like to be able to do is to have those child elements maintain their positions in three-dimensional space. And that's what Preserve3D does.

There's a little wrinkle here in that it's hard to have a 3D hierarchy of elements, but still implement overflow style in CSS. If you want overflow hidden or overflow scroll, how does that interact with 3D? It gets kind of weird. So actually, if you need to clip-- in other words, if you need to overflow style, that's going to cause flattening. That's going to override the transform style 3D.

So let's go back to our ring now. Hopefully it'll look better this time. So we're setting Preserve 3D on the ring. Notice that's on the ring, so it's going to affect the child elements. It's going to avoid the posters being flattened. And now let's try our Y rotation again. That looks much better. OK.

OK, we're happy now. Well, actually, I must admit, we have been cheating. This is really what it looks like so far. OK, it is 3D. It's not being flattened. We don't see this plane swinging by. But we don't have any perspective, so it looks very flat. So we need to add some perspective to get a really 3D appearance. And the way we do that is to set a style rule on the container element, which is WebKit perspective. And that's going to make it look like this.

And what perspective does is it gives you the vanishing point perspective that you know from geometry. There's one more thing we need to do to make it quite like the example, which is to set the origin of the perspective. And that makes us look as if we're looking down on the top of the object.

So let's look at perspective a little more rigorously here. So the property name is WebKit Perspective, and it takes a numeric value, which is a depth. And I'll explain that in a moment. So what perspective is doing is it's setting up a 3D-- or it's setting up the perspective for a three-dimensional scene. So what it does is affect how unflattened, transformed child elements are going to be rendered. And the value there, this mysterious depth value, is the distance of the viewer from the z equals zero plane. That's kind of confusing, so let's look at a picture.

So here we have three elements with no perspective right now. And we're looking from the side here. So the element on the right-hand side has had a negative Z translate. So it's behind the plane, which is the gray box. And then the element on the left has a positive Z translate. So that one's closer to the viewer. So with no perspective, all these elements look the same size, which is why our ring looked very flat when we saw it just now.

With some moderate amount of perspective, the element in the back looks smaller, and the element in the front looks like it's a little closer to us and actually has got larger. So we've got some amount of foreshortening. And now, if we add a stronger amount of perspective with a lower number, we get even more foreshortening. So that makes everything look like it's really kind of up front in our face.

And as we saw in the example just now, we can also control the origin of the perspective with WebKit Perspective Origin. And this behaves very similarly to Transform Origin that I mentioned earlier. There's one more thing which we might want to do if this was some real web content, especially on a small screen like the iPhone screen.

You'll notice that the elements in the back-- 7, 8, and 9, the numbers there-- are flipped around, obviously, by the transform, but we can still see them. And the numbers are backwards. The text will be backwards if there was text there. You can imagine these elements being rendered onto a sheet of glass. So we can kind of see the backside of the window, if you like. And that might not be what you want, always. So we can hide those elements that are facing away from the viewer with a property called WebKitBackfaceVisibility.

So let's look at that in a bit more detail. WebKit Backface Visibility is the property. And it has two values-- visible, which is the default, which means that you can see both sides of the element, and then hidden. And hidden is the one we want to use here.

And what hidden does is if an element is facing away from the viewer-- in other words, if you could see the back face of that element-- it means that that element both will disappear from view. It won't be rendered. And also, it will not respond to hit testing. So that element kind of disappears from the scene.

So let's apply that to our ring. And let's run the animation again so you can see what happens. Let's run the animation again so you can see what happens. OK. So now you only see the elements when they're facing towards you. And that cleans up the appearance quite a bit, especially if there was more information in there.

So probably 90% of the things you'll need to do with 3D transforms you can do with what I've told you already. If you have some really advanced use, you want to get really fancy, then start taking notes. I mentioned before that 3D transforms are usually described in terms of 4x4 matrices. And I already mentioned that there's this matrix 3D value for WebKit Transform where you can specify the 16 numbers, which are the 4x4 matrix.

Maybe you want to actually read that value back out in JavaScript and do some math with it. So we've added a JavaScript object called WebKit CSS Matrix. And you can use this to do matrix math in JavaScript. So you can create one. You can assign it a string, which is this matrix3D string. And then you can call APIs on the object to do math. You can do scales and rotates and all the basic 3D transforms. And then you can read out a string back, which is a matrix3D string, which you can just plug straight into the WebKit transform style.

Sometimes you need to know what the current value of the transform is. And you can do this in the standard way that you read back CSS properties in JavaScript. And that's to use window.getComputedStyle. And of course, we're accessing the WebKit transform property on this. And this will give you back the current value of the transform, even if the element currently has a transitional animation running on it. So you can imagine it's snapshotting the current transform on the element and then handing it back to you.

Now, when you start doing 3D transforms, point mapping kind of starts to get complicated as well. But the basic story is that it works exactly as you expect. Even if you transform an element, you can still interact with it, and the points will hit the right points in that element. And if you use document element from point in your JavaScript, that's also going to return the element which is actually under the point, taking transforms into account.

Now, sometimes when you're doing event handling, maybe you're looking at event.pageX, pageY, you might need to convert points between elements and take transforms into account. And we've added a couple of new APIs that let you do that. Window.convertPoint from page to node, and the one that goes the other way, convertPoint from node to page.

So that was CSS Transforms. That was a lot of information in a short time, so let me just go over it briefly again. What we've done is to extend the existing WebKit Transform property with some new values that let you describe three-dimensional transforms. And then we allow you to control the perspective in the scene to really give it a 3D appearance with WebKit Perspective and WebKit Perspective Origin.

Now, I said that there was this problem with HTML with flattening, and so we can control whether flattening occurs or not using the WebKit transform style. And preserve3D is the value you want to avoid flattening. And then we talked about hiding backfaces when things are facing away from the viewer, which you can do with WebKit Backface Visibility Hidden. And 3D transforms, as I mentioned before, are only available in Safari on iPhone 2.0.

So we've got these three big new features. We've got-- well, actually four. We've got 2D transforms. We've got transitions. We've got 3D transforms. And we've got keyframe animations. And then you've probably been hearing about some of the other really cool features in Safari on iPhone now. You've got touch events and gestures and all these other good stuff.

So let's see what we can do when we put all these things together. And I'll have Dean come back on the stage. And we'll go through the demo that Gilles showed you earlier. But we'll link it back to the content you've seen and explain how it was put together.

So we're just going to start with a point that Simon made during the last slide, which was that-- that you can interact with form elements. So for some reason, he's taken a picture of my mother-in-law, and he's labeled -- actually, I should say, I'm sorry, Mrs. Maxwell. But let's say he's added some metadata to that, and I want to change it, so I just -- I tap on the element.

And I've got this cool 3D transition that's come out and brought in the form element. And you'll notice that the form elements have been transformed in 3D just as normal web content is. It's not quite that visible, but you'll see that for the title as a text field and the right-most side of the text field is a little bit higher than the left side because of the perspective where, you know, it's closer to you, the viewer. So, you know, now I can just tap on this field and up pops the typical keyboard, and I can erase what's there, give it a more accurate title.

And I can move on to the next element. You can see here I've got the drop-down box. And of course, this is definitely family and so on. And again, I can tap the R. fingers were there, tap the checkbox. So again, what this is saying is that you don't necessarily have to change the way your web application is. You can just start adding the 3D transforms. You don't have to redesign things. You can use existing form elements in your page. So now I'll go back and I'll show you the example that Jill showed earlier, which is the fingertips.

Now, it's important to realize this is just Safari. This is a web page. There's no plug-ins. There's nothing extra here. All we've done is use a bit of JavaScript and a bit of CSS to give this effect. This is an ordered list in HTML, and we've applied a style to the list elements, which transforms them in 3D.

You can see that we've got -- this is basically what we call a carousel. It's a ring on its side that's side onto the viewer. Now, in iPhone, the typical way you browse lists is to -- you touch and you move things around, but people know -- you already all know that if on a web page you touch and drag a page, the page scrolls or pans.

So what we've done here is we've -- we catch the touch events on the page, and instead of making the page move, we actually change the 3D rotation on the carousel element. So here I am touching the page, and I can move it. And even better, I can add a flick here, and you'll see we've got this animation where the ring slows down.

I want to pick this one that's a browse and cover flow. I just touch it. It moves to the center. The ring -- the carousel rotated, moved to the center, and then another page slid in. Now, again, you might have seen these slides with something like IUI, but here we've got this really quick transitions because, again, we've used the WebKit CSS transitions.

I've just got a page sitting off to the right side. When I touch on it, I set the property, the left property or the translation to be moved into the view, and it just slides in. I haven't had to do the animation. The web browser's done that for me.

You'll also notice we've got touch events on the stars, so I can give -- on the stars, I can give the video a rating. And in this case, we've got a custom control that's -- sorry, we've got a movie here with a custom control that's controlled by a -- by a JavaScript.

So this play button is, in fact, an image that's styled using CSS. And when I touch on that, I've got a JavaScript handle that starts the movie playing. Okay. And then we have the fingertip demo. So before it goes on further, I'll-- A brief way to look at your music library. I won't play "Hit Me" on my iPhone.

Also, as you've shown, when we rotate the phone, and we'll go back to the view, we've actually, we notice that the phone is rotated and we use a different style sheet. So instead of now the vertical ring, we've got a horizontal ring, and again, we've got the same features on that and a different layout on the page.

So that's for the demo. The really thing we want to drive home is, again, this is just using CSS. Technology is already familiar with it. It's really simple. And we've done, we've managed to create these awesome demos. So we're really looking forward to see what stuff you guys come up with with Safari on iPhone 2.0. And with that, I'll give it back to Simon to conclude.

OK. So you've seen a lot of cool stuff in these demos. And there was some amount of blood, sweat, and tears to get them running and to optimize the engine so that everything runs smoothly. So let's talk about performance. You'll notice that in a lot of the examples, we've been using WebKit Transform for our transitions and animations.

And there's a very good reason for that, which is it's one of the few properties that are currently hardware-accelerated. So if you want really smooth transitions on the phone, you want to use transitions and animations of WebKit Transform or Opacity. Those two are hardware accelerated, and those will give you great performance.

In order to get the best possible animations without any stuttering or without any delays, you want to avoid trying to do work. You want to avoid the web engine doing work while your animations are running. What does that mean? Well, you want to try and avoid layout and redraw.

Now, layout is essentially what the web engine does when you add content to your web page or when you change display style or set height and width and things like that. It has to recompute the positions of all the elements on the page, and that's expensive. So we don't want that to interrupt the performance of the animations. And then redraw is what happens when you change something like a background image or a color. And that's also going to cause a bit of a stutter in your animation, so you want to try and avoid those to get best performance.

One point-- you can use the simulator that comes with the SDK to do all your web development, because it has all these features in it. But when it comes down to testing the performance of your content, you should really test on the phone, because the iPhone will give you the same experience that your customers get when they go to your website.

So let me summarize what we've learned today. We have these new presentation features. And these fall under the umbrella that you've probably heard at the conference of CSS visual effects. And the specific ones I talked about today are 2D transforms and 3D transforms, transitions, and keyframe animations. And there's a lot of stuff here. We've talked about it a lot in today's session.

And in the demos, you can also see that when you mix and match these with the other new features like touch events and gestures, you can start creating some really rich user interactions in your iPhone Web Applications. We've also got these media playback APIs, which means you don't have to have a plug-in sitting there on the page the whole time. You can call from JavaScript. You can tell it to play, and it'll just go full screen and start playing. We want you to go out and learn about these new features and create really cool stuff. And we're very excited to see what you will produce with these.

Let me tell you a bit about how to get started with these. First of all, they're all documented on developer.apple.com/webapps. I pointed you at the specs earlier. On apple.com here, we have some annotated version of the specs that use all the WebKit prefixes. And so you should look at those first, and it'll reduce the amount of confusion. And then if you have questions, you should send email to Vicki Murley or Mark Malone, who are our technology evangelists.

And then we have a couple more sessions, certainly one session tomorrow morning at 9:00 in this room, where Antoine is going to show you step-by-step how to build that spinning ring example. And so in that session, you'll learn the hands-on of how to apply 3D transforms, how to handle touch events, and how to call these new media APIs. And then there are a couple of labs. There's one, the Rich Graphics in Safari Lab, which is at 5:00, which is basically right now downstairs after the session. And then tomorrow, there's a lab called iPhone Web Application Development, and that's at 3:30 in Lab A.

So I've given you a lot of information, but let me give you the high-level picture. So what? What have we given you? Well, we've given you a declarative 3D modeling and animation framework. You've got 3D transforms. You've got transitions, keyframe animations. It's hardware-accelerated. But we've done this in a technology you already know. This is in HTML, CSS, and JavaScript. So it should be really easy for you to pick up and get running and create some incredibly cool content. And we just can't wait to see what you're going to do with this.