Logo

iNVASIVECODE - Blog

  • Archive
  • RSS
  • Ask us anything about iOS
banner
Transform Layers

In the previous post, I showed you how to use the replicator layer class (CAReplicatorLayer). The main problem with layers is that if you want to render them in 3D is quite hard. You need to apply a 3D transformation to each sublayer, fight against the anchor point to get the right transformations. Then, you have to apply a 3D transformation to the root layer and change the m34 value of the 3D transformation matrix to simulate the prospective. 

If you don’t do that, everything looks flat. Transform layers are the solution to this. So, this time I want to show you another interesting core animation layer that can be used to create a 3D layer hierarchy, rather than the flattened hierarchy rendering model used by other CALayer classes.
To better understand what I am talking about, this video shows what you can do with a CATransformLayer. I created this small animation to let you understand how it works:



This animated cube is obtained using the CATransformLayer class. Here the source code, I used to build the small cube:

- (CATransformLayer *)generateTransformLayerTree
{
    // Create a transform layer
    CATransformLayer *transformLayer = [CATransformLayer layer];
    transformLayer.bounds = FRAME;

    CGPoint centralPoint = 
            CGPointMake(transformLayer.bounds.size.width/2.0, 
                transformLayer.bounds.size.height/2.0);

    // This is the first side of the cube
    CALayer *layer1 = [CALayer layer];
    layer1.bounds = FRAME;
    layer1.position = centralPoint;
    layer1.borderColor = [[UIColor lightGrayColor] CGColor];
    layer1.borderWidth = BORDERWIDTH;
    layer1.backgroundColor = [[UIColor colorWithRed:1.0 
                green:0 
                blue:0 
                alpha:.7] CGColor];

    // This is the second side. Notice that a 3D transform is applied to it
    // to rotate it of 90° along the y axis and translate it
    CALayer *layer2 = [CALayer layer];
    layer2.bounds = FRAME;
    layer2.position = centralPoint;
    layer2.borderColor = [[UIColor lightGrayColor] CGColor];
    layer2.borderWidth = BORDERWIDTH;
    layer2.backgroundColor = [[UIColor colorWithRed:0.0 
                green:1.0 
                blue:0.0 
                alpha:0.7] CGColor];
    CGFloat degrees = 90.0;
    CGFloat radians = DegreesToRadians(degrees);
    CATransform3D t1 = CATransform3DIdentity;
    t1 = CATransform3DRotate(t1, radians, 0.0f, 1.0f, 0.0f);
    t1 = CATransform3DTranslate(t1, 0, 0, SQUARE_SIZE/2.0f);
    t1 = CATransform3DTranslate(t1, SQUARE_SIZE/2.0f, 0.0f, 0.0f);
    layer2.transform = t1;

    // This is the 3rd side of the cube. This goes behind the first square.
    CALayer *layer3 = [CALayer layer];
    layer3.bounds = FRAME;
    layer3.position = centralPoint;
    layer3.borderColor = [[UIColor lightGrayColor] CGColor];
    layer3.borderWidth = BORDERWIDTH;
    layer3.backgroundColor = [[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.7f] CGColor];
    t1 = CATransform3DIdentity;
    t1 = CATransform3DTranslate(t1, 0.0f, 0.0f, -SQUARE_SIZE);
    layer3.transform = t1;

    // Finally, the last side.
    CALayer *layer4 = [CALayer layer];
    layer4.bounds = FRAME;
    layer4.position = centralPoint;
    layer4.borderColor = [[UIColor lightGrayColor] CGColor];
    layer4.borderWidth = BORDERWIDTH;
    layer4.backgroundColor = [[UIColor colorWithRed:1.0 
                green:1.0 
                blue:1.0 
                alpha:0.7] CGColor];
    t1 = CATransform3DIdentity;
    t1 = CATransform3DRotate(t1, radians, 0.0, 1.0, 0.0);
    t1 = CATransform3DTranslate(t1, 0, 0, -SQUARE_SIZE/2.0f);
    t1 = CATransform3DTranslate(t1, SQUARE_SIZE/2.0f, 0.0f, 0.0f);
    layer4.transform = t1;

    [transformLayer addSublayer:layer1];
    [transformLayer addSublayer:layer2];
    [transformLayer addSublayer:layer3];
    [transformLayer addSublayer:layer4];

    // Place the anchorPoint in the center of the cube
    transformLayer.anchorPointZ = -SQUARE_SIZE/2.0;

    return transformLayer;
}


You need some defines for this source code. Here, they are:

#define SQUARE_SIZE     300.0f
#define FRAME   CGRectMake(0.0f, 0.0f, SQUARE_SIZE, SQUARE_SIZE)
#define BORDERWIDTH     1.0f


So, now let’s try to understand what I did. First of all, I created an open face cube: it has only four sides. I leave you as exercise to add the top and bottom side. 
The first side I creates is a red square (layer1). I placed it in the center of the transform layer. Nothing new here, right?
The third side (layer3) goes behind the first side at the distance of SQUARE_SIZE points. So, I created again a rectangle and applied to it a translation of -SQUARE_SIZE points. Now, the left (layer4) and right (layer2) sides are similar. They are first rotated 90° with respect to the y axis and then translated to left and to the right, respectively. Finally, they are translated to the back (inside the screen) half SQUARE_SIZE.
Finally, I added the four layers to the transform layer and to make the transformations work correctly I moved the anchorPointZ to the center of the cube. In this way, when you apply any animation to the transform layer everything is transformed correctly.

Now, what happens if we combine the replicator layer from the previous post and this transform layer. Well, here it is an example:



If you liked this post, check here our iOS training classes. You can learn more about these and other really advanced topic topics.

Keep coding,
Geppy
Pop-upView Separately

Transform Layers

In the previous post, I showed you how to use the replicator layer class (CAReplicatorLayer). The main problem with layers is that if you want to render them in 3D is quite hard. You need to apply a 3D transformation to each sublayer, fight against the anchor point to get the right transformations. Then, you have to apply a 3D transformation to the root layer and change the m34 value of the 3D transformation matrix to simulate the prospective. If you don’t do that, everything looks flat. Transform layers are the solution to this. So, this time I want to show you another interesting core animation layer that can be used to create a 3D layer hierarchy, rather than the flattened hierarchy rendering model used by other CALayer classes. To better understand what I am talking about, this video shows what you can do with a CATransformLayer. I created this small animation to let you understand how it works:

This animated cube is obtained using the CATransformLayer class. Here the source code, I used to build the small cube:

- (CATransformLayer *)generateTransformLayerTree
{
    // Create a transform layer
    CATransformLayer *transformLayer = [CATransformLayer layer];
    transformLayer.bounds = FRAME;

    CGPoint centralPoint = 
            CGPointMake(transformLayer.bounds.size.width/2.0, 
                transformLayer.bounds.size.height/2.0);

    // This is the first side of the cube
    CALayer *layer1 = [CALayer layer];
    layer1.bounds = FRAME;
    layer1.position = centralPoint;
    layer1.borderColor = [[UIColor lightGrayColor] CGColor];
    layer1.borderWidth = BORDERWIDTH;
    layer1.backgroundColor = [[UIColor colorWithRed:1.0 
                green:0 
                blue:0 
                alpha:.7] CGColor];

    // This is the second side. Notice that a 3D transform is applied to it
    // to rotate it of 90° along the y axis and translate it
    CALayer *layer2 = [CALayer layer];
    layer2.bounds = FRAME;
    layer2.position = centralPoint;
    layer2.borderColor = [[UIColor lightGrayColor] CGColor];
    layer2.borderWidth = BORDERWIDTH;
    layer2.backgroundColor = [[UIColor colorWithRed:0.0 
                green:1.0 
                blue:0.0 
                alpha:0.7] CGColor];
    CGFloat degrees = 90.0;
    CGFloat radians = DegreesToRadians(degrees);
    CATransform3D t1 = CATransform3DIdentity;
    t1 = CATransform3DRotate(t1, radians, 0.0f, 1.0f, 0.0f);
    t1 = CATransform3DTranslate(t1, 0, 0, SQUARE_SIZE/2.0f);
    t1 = CATransform3DTranslate(t1, SQUARE_SIZE/2.0f, 0.0f, 0.0f);
    layer2.transform = t1;

    // This is the 3rd side of the cube. This goes behind the first square.
    CALayer *layer3 = [CALayer layer];
    layer3.bounds = FRAME;
    layer3.position = centralPoint;
    layer3.borderColor = [[UIColor lightGrayColor] CGColor];
    layer3.borderWidth = BORDERWIDTH;
    layer3.backgroundColor = [[UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:0.7f] CGColor];
    t1 = CATransform3DIdentity;
    t1 = CATransform3DTranslate(t1, 0.0f, 0.0f, -SQUARE_SIZE);
    layer3.transform = t1;

    // Finally, the last side.
    CALayer *layer4 = [CALayer layer];
    layer4.bounds = FRAME;
    layer4.position = centralPoint;
    layer4.borderColor = [[UIColor lightGrayColor] CGColor];
    layer4.borderWidth = BORDERWIDTH;
    layer4.backgroundColor = [[UIColor colorWithRed:1.0 
                green:1.0 
                blue:1.0 
                alpha:0.7] CGColor];
    t1 = CATransform3DIdentity;
    t1 = CATransform3DRotate(t1, radians, 0.0, 1.0, 0.0);
    t1 = CATransform3DTranslate(t1, 0, 0, -SQUARE_SIZE/2.0f);
    t1 = CATransform3DTranslate(t1, SQUARE_SIZE/2.0f, 0.0f, 0.0f);
    layer4.transform = t1;

    [transformLayer addSublayer:layer1];
    [transformLayer addSublayer:layer2];
    [transformLayer addSublayer:layer3];
    [transformLayer addSublayer:layer4];

    // Place the anchorPoint in the center of the cube
    transformLayer.anchorPointZ = -SQUARE_SIZE/2.0;

    return transformLayer;
}

You need some defines for this source code. Here, they are:

#define SQUARE_SIZE     300.0f
#define FRAME   CGRectMake(0.0f, 0.0f, SQUARE_SIZE, SQUARE_SIZE)
#define BORDERWIDTH     1.0f

So, now let’s try to understand what I did. First of all, I created an open face cube: it has only four sides. I leave you as exercise to add the top and bottom side. The first side I creates is a red square (layer1). I placed it in the center of the transform layer. Nothing new here, right? The third side (layer3) goes behind the first side at the distance of SQUARE_SIZE points. So, I created again a rectangle and applied to it a translation of -SQUARE_SIZE points. Now, the left (layer4) and right (layer2) sides are similar. They are first rotated 90° with respect to the y axis and then translated to left and to the right, respectively. Finally, they are translated to the back (inside the screen) half SQUARE_SIZE. Finally, I added the four layers to the transform layer and to make the transformations work correctly I moved the anchorPointZ to the center of the cube. In this way, when you apply any animation to the transform layer everything is transformed correctly.

Now, what happens if we combine the replicator layer from the previous post and this transform layer. Well, here it is an example:

If you liked this post, check here our iOS training classes. You can learn more about these and other really advanced topic topics.

Keep coding, Geppy

    • #core animation
    • #transform layer
    • #catransformlayer
    • #replicator layer
    • #careplicatorlayer
    • #iOS training
    • #ios 6 training
    • #iOS course
    • #san francisco
    • #barcelona
  • 9 months ago
  • 4
  • Permalink
  • Share
    Tweet

4 Notes/ Hide

  1. hankbao likes this
  2. bgnori-technology reblogged this from do-nothing
  3. do-nothing reblogged this from invasivecode
  4. succistent likes this
  5. invasivecode posted this
← Previous • Next →
iNVASIVECODE is a design and development enterprise with the passion for engineering beautiful iOS and OS X apps.

iNVASIVECODE offers 5-days iOS training classes for professional developers and on-site technical consulting.

Pages

  • HOME
  • iOS TRAINING CLASSES
  • TUTORIAL ON CORE TEXT
  • QUARTZ CRASH COURSE
  • CONTACT US

More about us

  • @invasivecode on Twitter
  • Google
  • Linkedin Profile

loading tweets…

I Dig These Posts

See more →
  • RSS
  • Random
  • Archive
  • Ask us anything about iOS
  • Mobile

Copyright ©2008-2013 iNVASIVECODE, Inc. Effector Theme by Carlo Franco.

Powered by Tumblr