使用具有不同Z和速度值的CALayer滚动以获得视差效果

1 iphone core-animation calayer uiscrollview

我按以下顺序为每个背景图像创建了Layer:

-(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];
    }   
Run Code Online (Sandbox Code Playgroud)

我可以一个接一个地看到图像,一切正常,现在我想实现滚动.您会注意到我创建了具有不同速度和Z值的每个图层,以便在渲染到视图时基本上创建视差效果.在我走这条路之前,这些价值观会带我到我想去的地方吗?也就是说,Z值和图层的速度值会给我带来我想要看作视图子层的效果吗?

谢谢ER

Mat*_*ong 7

首先,我要提一下,你的评论大多是多余的,让你的代码更难阅读,而不是更容易.告诉我,/* Adding each layer to the layer of the view. */当一行后来你调用一个名为的方法-addSublayer只是噪音.这个名字-addSublayer足够描述.如果人们无法弄明白,他们就不应该编写代码.此外,它对将来必须维护您的代码(包括您)的任何人都无济于事.它只会觉得需要更多的代码才能实现.

其次,你有一些不必要的代码效率低下.以下是一些帮助提示:

  1. 使用快速枚举.因为循环很慢.

  2. 没有理由为加载图像创建数据提供者引用.只要使用-imageWithContentsOfFile代替

  3. 忘记使用CAScrollLayer.使用它没有任何好处.UIScrollView将提供您需要的一切,并且实现起来更加简单.您只需根据内容的范围设置UIScrollView 的contentSize属性.这意味着您必须计算它,但它比尝试使CAScrollLayer正常工作简单得多.我相信CAScrollLayer会根据其子层计算内容区域,所以你所能做的就是按照你已经做的那样添加它们.如果滚动功能尚未完成,您还有另一个理由要废弃它以支持UIScrollView.

这是我如何简化你的代码(除了交换滚动图层的滚动视图.这是留给读者的练习.;-)

- (void)SetView
{      
  NSString *plistPath = [[NSBundle mainBundle] 
                              pathForResource:plistName ofType:@"plist"];

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

  int i = 0;

  for (NSString *imageName in array) // fast enumeration
  {
    subLayer = [[CAScrollLayer alloc] init];

    NSString *fileName = [[NSBundle mainBundle] 
                             pathForResource:imageName ofType:@"png"];

    UIImage *image = [UIImage imageWithContentsOfFile:filename];

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

    subLayer.frame = CGRectMake(0, 0,480,320);
    subLayer.speed = (float)i;
    subLayer.zPosition = (float)i;

    [self.layer addSublayer:subLayer];

    i++;
  }
  [array release];
}
Run Code Online (Sandbox Code Playgroud)

最后,为了回应你是否能获得视差效果,我认为它可能会非常艰难,因为Core Animation层不支持摄像机角度的概念.您最接近的是,我认为是在您添加到层次结构的每个图层上设置变换.您可以设置转换的z转换并启用透视图(通过设置CATransfor3D结构的.m34字段).你可以在这一点上玩围绕包含层的旋转和子层的x平移,以试图获得你正在寻找的效果.最重要的是它不会发生.您将不得不大量使用这些值,最终可能最好使用OpenGL,具体取决于您的视差需要多么令人信服.