Advertise Books Events Forum News Social Networking Support Us

sdkIQ for iPhone
($4.99)

Shape Up
($0.99)

Your First iPhone App
($1.99)

iVidCam Free
(free)

Kid Art
($0.99)

iPUBQUIZ
(£1.19)

ArtStudio
($3.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Tutorials

Reply
 
LinkBack Thread Tools Display Modes
Old 06-30-2009, 09:28 AM   #1 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 3
Default 3D Cube View Transition On iPhone

Today I'm glad to introduce you how I implement a simple 3D Cube transition with Core Animation on iPhone. As the matter of fact, I always think that Mac's 3D Cube Transition used for user account switch is really an amazing view switch effect, but since there isn't one I can use on iPhone, at least I didn't find one, I decided to implement it by myself. To make it easier to be integrated in my code, I followed the sample of TransitionView provided by Apple, and implement a new TransitionView with 3D Cube Transition.

For better format, you can access our blog site
Check how 3D Cube effect work

Customized TransitionView

Like iPhone TransitionView sample, my TransitionView can be used as a parent view for all views which are going to be switched in or switched out, so all subviews will be added or removed along with a 3D Cube transition, all you need to do is set direction and duration parameters.

To help you clearly understand how it works, I'd like to use a example to illustrate it. The example is very simple, it has two views, we can click "NEXT" button on view one to jump to view two along with 3D Cube transition. You will be able to see what it looks like with your simulator.

Source Code

The code for this sample is available on Google Code. You can use svn to checkout it and compile it with Xcode 3.0.

svn checkout cubetransition - Revision 4: /trunk cubetransition-read-only

After check out the source code, and launch the demo app in simulator, you can watch the 3D effect by clicking NEXT and then BACK button.

3D Cube Transition

The idea for implementing 3D effect is pretty simple. Firstly, we need to figure out a way to construct a 3D model structure once the new added view need to replace the old view, after we construct a 3D layer model, we need to calculate the target position of x, y, z and degrees need to rotate, then commit the transition and wait for transition finished. In animation finish callback, we need also to recover TransitionView and finally add the new
view in it. So let me show you how to do it.

Construct 3D model structure

Since iPhone Core Animation don't support rotate a non image layer, so firstly, we have to capture current old view and new view and generate a CGImage, in this example, I capture image for old view evevrytime, you can decided to cache the image for later use.

Capture view as image

Code:
- (id) captureView:(UIView *)view isMasked:(BOOL)aIsMasked
{
UIGraphicsBeginImageContext(view.frame.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
if (aIsMasked) {
CGContextSetRGBFillColor (UIGraphicsGetCurrentContext(), 0, 0, 0, MASKALPHA);
CGContextFillRect (UIGraphicsGetCurrentContext(), view.frame);
}
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return (id) [newImage CGImage];
}
captureView is used to generate a image regarding current graphic context. note: isMasked is used to indicate if we want to gray the view to indicate the change.

Construct transformed layer

Code:
transformed = [CALayer layer];
transformed.frame = self.bounds;
transformed.anchorPoint = CGPointMake(0.5f, 0.5f);
CATransform3D sublayerTransform = CATransform3DIdentity;

/* Set perspective */
sublayerTransform.m34 = 1.0 / -1000;
[transformed setSublayerTransform:sublayerTransform];
[self.layer addSublayer:transformed];

//init Sublayers
CATransform3D t = CATransform3DMakeTranslation(0, 0, 0);
[transformed addSublayer:[self makeSurface:t withView:mySubView isMasked:aIsMasked]];
[mySubView setHidden:YES];
if (aDirection == RTOL)
{
t = CATransform3DRotate(t, radians(90), 0, 1, 0);
t = CATransform3DTranslate(t, CUBESIZE, 0, 0);
[transformed addSublayer:[self makeSurface:t withView:aNewView isMasked:aIsMasked]];
}
- (id) captureView:(UIView *)view    isMasked:(BOOL)aIsMasked{UIGraphicsBeginImageContext(view.frame.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];if (aIsMasked) { CGContextSetRGBFillColor (UIGraphicsGetCurrentContext(), 0, 0, 0, MASKALPHA); CGContextFillRect (UIGraphicsGetCurrentContext(), view.frame);}UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();return (id) [newImage CGImage];
}
Firstly, we need to create a layer for transform, this layer is main layer of 3D rotation, we also need to initialize 3D 4-by-4 matrix by setting CATransform3DIdentity. Then we need to set perspective, this is a very important step. Applying the 3D perspective relies on a poorly-documented feature of Core Animation’s CATransform3D structure, a 4-by-4 matrix used to perform matrix transformations. Apple’s documentation says that changes to CATransform3D.m34 “affect the sharpness of the transform.” For our purposes, this means “make things look 3D”. Till now, we have create the main layer and set perspective, then we need to set anchor, when we rotate the transformed layer, we need to follow anchor to rotate, so anchor is used for it, before SDK 3.0, we can only set anchor at x,y axis, in 3.0, we are able to set anchor on z axis, in this example, we will still set anchor on x,y axis, which means we need do some specially steps to under the change on z axis, we will talk about it later. Now, we need to place the captured view images on its position, the first view is placed at the default position, that means all its position x, y, z are 0, and it don't have any initial rotate. The second view need to be placed in a 3D space, so we need to rotate this layer 90 degree along with Y axis, then we need to place it an x=330, y=0, z=0. So now, we have constructed 2 faces of a cube, and that is enough to do 3D transition.

Rotate transformed layer

Code:
CAAnimationGroup *group = [CAAnimationGroup animation];
group.delegate = self;
group.duration = aDuration;

translationX = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.translation.x"];
translationX.toValue = [NSNumber numberWithFloat:-(CUBE_VERTICAL_WIDTH / 2)];
rotation = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.rotation.y"];
rotation.toValue = [NSNumber numberWithFloat:radians(-90)];
translationZ = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.translation.z"];
translationZ.toValue = [NSNumber numberWithFloat:-(CUBE_VERTICAL_WIDTH / 2)];
group.animations = [NSArray arrayWithObjects: rotation, translationX, translationZ, nil];
[transformed addAnimation:group forKey:kAnimationKey];
Firstly, we need to create a CAAnimationGroup, the reason we create it is because we need use about 3 transitions to change layers position together. The first transition we use is change the layer's x position, if we don't change it, a half of cube will be rotated outside screen. The second transition we use is rotate the layer by 90 degree. The third transition we used is change the layer's z position, if we don't change it, the cube will become more closed to screen. Note, we change all position info based on key-value mechanism. After we created the group of transition, we added the transitions to the transformed layer, and then it will automatically rotate the layers in 3D space.

Handle transitions status

Handle transitions status is very important for view switch, in this example, we removed the old view after the transition is started, and add the new view after the transition is stopped. With those status and status handling, we can formally finish view switch.

Conculsion

That is all about 3D cube transition, it is very easy to be adopted and very efficient, you can also refer to the code in example to see how to use it in the real world.

Last edited by Kalimba; 06-30-2009 at 10:25 AM. Reason: Added [CODE] tags
antoxu is offline   Reply With Quote
Old 06-30-2009, 10:27 AM   #2 (permalink)
Pro. Game Developer
iPhone Dev SDK Supporter
 
Join Date: Feb 2009
Location: ¿La Islas Hermosas?
Posts: 1,421
Default

Thanks for posting. I've moved the post to the Tutorials section and added CODE tags to make the code more readable.
__________________
piña para la niña interactive
Kalimba is online now   Reply With Quote
Old 06-30-2009, 11:46 AM   #3 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 3
Default

Quote:
Originally Posted by Kalimba View Post
Thanks for posting. I've moved the post to the Tutorials section and added CODE tags to make the code more readable.
Thank you very much, it is really helpful.
antoxu is offline   Reply With Quote
Old 10-06-2009, 08:05 AM   #4 (permalink)
Registered Member
 
Join Date: Oct 2009
Posts: 34
Default

I'm digging up an old thread, but this was very helpful, and so easy to implement. thanks!

In case anyone else is interested, I added easing to this transition by adding the following line to the moveFrom method:

Code:
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
Quick question though ... in the middle of a transition I see white in the background. Is there anyway to make this another color, or even better, an image? It probably depends on how I have my project structured, but if you could give me some points it would be great.

thanks again
wbm234 is offline   Reply With Quote
Old 10-06-2009, 08:58 AM   #5 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 3
Default

Quote:
Originally Posted by wbm234 View Post
I'm digging up an old thread, but this was very helpful, and so easy to implement. thanks!

In case anyone else is interested, I added easing to this transition by adding the following line to the moveFrom method:

Code:
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
Quick question though ... in the middle of a transition I see white in the background. Is there anyway to make this another color, or even better, an image? It probably depends on how I have my project structured, but if you could give me some points it would be great.

thanks again
Yes, it would be better to add timing function make transition nicely.

For changing the color, you can set color or image for transition view by changing the code below

Code:
- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        mySubView = nil;
        transitioning = NO;
        self.backgroundColor = [UIColor clearColor]; //change your color here
    }
    return self;
}
antoxu is offline   Reply With Quote
Old 01-02-2010, 04:09 PM   #6 (permalink)
Indie Dev
 
hm50's Avatar
 
Join Date: May 2009
Location: South Bend, Indiana
Posts: 101
Post

Nice Job! I was studying this a bit as I am looking to create the same effect, but not to the entire view. I have multiple UIImageViews 30x30 on my view that I would like to rotate in a cube like fashion. Is there a way to simplify this code easily to only handle the "multiple" UIImageViews on my main view. Imagine a button that when clicked rotates the UIImageView (with your method) to reveal all four sides of the cube. Other issue is that the images for the multiple instances would be different and set dynamically.

Thanks for any help!
__________________
iPhone 3G

Support Indie Devs!! (that goes for newbs too!)

Apps:
See Read Say
iStatus
hm50 is offline   Reply With Quote
Old 01-03-2010, 07:30 AM   #7 (permalink)
Registered Member
 
Join Date: Dec 2009
Location: Arlington
Posts: 1
Send a message via AIM to rosetodd33 Send a message via Yahoo to rosetodd33 Send a message via Skype™ to rosetodd33
Default

thkz man
nice post



glasgow
rosetodd33 is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On
Trackbacks are On
Pingbacks are On
Refbacks are On


Enter the iPhone App Challenge!  Win $500!
» Advertisements
» Stats
Members: 24,130
Threads: 38,899
Posts: 170,662
Top Poster: smasher (2,565)
Welcome to our newest member, HunBirk427
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 02:41 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0