Search code examples
iphoneuiscrollviewcore-animationcalayer

Scrolling with CALayer with different Z and speed values for parallax effect


I have created Layer for each of my background images in the following order:

-(void)SetView
{

        /* Getting the plist path to load */

       NSString *plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:@"plist"];

        /* Printing the plistPath value */

        NSLog(@"plistPath:%@",plistPath);

        /* loading the image names to an array */

        NSArray *array = [[NSArray alloc] initWithContentsOfFile:plistPath];

        /* Creating loop to create each background image as a layer */

        for (int i=0; i< [array count]; i++) 
        {
            /* Set the image name of each index*/

            NSString *imageName = [array objectAtIndex:i];

            /* Printing the imageName value */

            NSLog(@"imageName: %@",imageName);


            /* allocate new CAScroll object */

            subLayer = [[CAScrollLayer alloc] init];


            /* Define const char as the image name.*/

            const char *fileName = [[[NSBundle mainBundle] pathForResource:imageName ofType:@"png"] UTF8String];

            /* Printing the fileName value */

             NSLog(@"fileName: %s",fileName);

            /* Setting the data reference as the image file name */

            CGDataProviderRef dataRef = CGDataProviderCreateWithFilename(fileName);

            /* Printing the dataRef value */

            NSLog(@"dataRef: %@",dataRef);

            /* Creating image reference supplying the image name as data source */

                CGImageRef image = CGImageCreateWithPNGDataProvider
                (dataRef, NULL, 
                 NO, kCGRenderingIntentDefault);


            /* Define the contents of the layer */

            subLayer.contents = (id)[UIImage imageWithCGImage:image scale:2.0 orientation: UIImageOrientationRight].CGImage;             

            /* Printing the contenet of the subLayer */

            NSLog(@" Print the content %@",subLayer.contents);


            /* Define the frame of the layer */
            subLayer.frame = CGRectMake(0, 0,480,320);

            /* The rate of the layer. Used to scale parent time to local time, e.g.
             * if rate is 2, local time progresses twice as fast as parent time.
             * Defaults to 1. */

            subLayer.speed = (float)i;

            /* The Z component of the layer's position in its superlayer. Defaults
             * to zero. Animatable. */

            subLayer.zPosition = (float)i;

            /* Adding each layer to the layer of the view. */

                [self.layer addSublayer:subLayer];



        }
        /* Release the array after adding all layers */

        [array release];
    }   

I can see the images one after the other and everything is ok, now I want to implement scrolling. You will notice that I created each layer with diffrent speed and Z value to basically create parallax efftect later on when rendering to the view. Before I am going with that path, are these values will lead me to where I want to go ? i.e will the Z value and the speed value of the layer will give me the effect that I want to see as sublayer of the view ?

Thanks ER


Solution

  • If you want a classic parallax effect (ie, stuff in the back scrolls slower than stuff in the front), you can dispense with the CoreAnimation trickery and simply implement it yourself.

    Just adjust the positions of your layers or views in response to scrolling, each frame. You can do this either as the UIScrollView delegate or by overriding, IIRC, -setBounds: or -layoutSubviews on the scrollview to do your own layout.

    The basic idea is that for things "behind" the main plane, you can shift them downwards as you scroll to achieve the illusion that they're staying where they are, but are just further back in Z.

    So, subtract a certain k * Y from your position values:

    layer.position = (CGPoint){logicalPosition.x, logicalPosition.y - k * contentOffset.y}
    

    Where you pick k in [0,1) depending on how much effect you want. You could also define this in terms of Z or a ratio or whatever math you like.