如何使用Core Animation堆叠图像以模拟深度?

Jef*_*ume 6 iphone core-animation

我有一系列UIImages,我需要用它来模拟深度.我无法使用缩放,因为我需要能够旋转父视图,并且图像应该看起来像是在彼此前面明显堆叠,而不是在同一平面上.

我创建了一个新的基于ViewController的项目并将其放在viewDidLoad中(以及附加的三个120x120像素图像,名为1.png,2.png和3.png):

- (void)viewDidLoad {

    // display image 3
    UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]];
    three.center = CGPointMake(160 + 60, 240 - 60);
    [self.view addSubview:three];

    // rotate image 3 around the z axis
    // THIS IS INCORRECT
    CATransform3D theTransform = three.layer.transform;
    theTransform.m34 = 1.0 / -1000;
    three.layer.transform = theTransform;

    // display image 2
    UIImageView *two = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.png"]];
    two.center = CGPointMake(160, 240);
    [self.view addSubview:two];

    // display image 1
    UIImageView *one = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.png"]];
    one.center = CGPointMake(160 - 60, 240 + 60);
    [self.view addSubview:one];

    //  rotate image 3 around the z axis
    // THIS IS INCORRECT
    theTransform = one.layer.transform;
    theTransform.m34 = 1.0 / 1000;
    one.layer.transform = theTransform;

    // release the images
    [one release];
    [two release];
    [three release];

    // rotate the parent view around the y axis
    theTransform = self.view.layer.transform;
    theTransform.m14 = 1.0 / -500;
    self.view.layer.transform = theTransform;

    [super viewDidLoad];
}
Run Code Online (Sandbox Code Playgroud)

我有非常具体的原因,为什么我没有使用EAGLView以及为什么我不将图像作为CALayers加载(即为什么我为每个使用UIImageViews).这只是一个快速演示,我可以使用它来准确地解决我在父应用程序中需要的内容.

是否有一些矩阵方式来沿z轴平移这些2D图像,所以它们看起来就像我想要表现的那样?我已经浏览了其他StackOverflow文章以及维基百科的参考文献,并且没有找到我正在寻找的东西 - 尽管我可能不一定使用正确的术语来解决我正在尝试做的事情.

Bra*_*son 7

为了堆叠您的视图,并让它们应用透视图,您需要先将它们放在不同的Z位置,然后将透视效果应用于包含图层.

我相信下面的代码会做到这一点,但我没有测试它(我已经做了类似于纯CALayers的事情,所以一般原则是正确的):

- (void)viewDidLoad {

    UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]];
    three.center = CGPointMake(160 + 60, 240 - 60);
    [self.view addSubview:three];

    three.layer.zPosition = -100;

    UIImageView *two = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.png"]];
    two.center = CGPointMake(160, 240);
    [self.view addSubview:two];

    two.layer.zPosition = 0;

    UIImageView *one = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.png"]];
    one.center = CGPointMake(160 - 60, 240 + 60);
    [self.view addSubview:one];

    one.layer.zPosition = 100;

    // release the images
    [one release];
    [two release];
    [three release];

    CATransform3D theTransform = self.view.layer.sublayerTransform;
    theTransform.m34 = 1.0 / -500;
    self.view.layer.sublayerTransform = theTransform;

    [super viewDidLoad];
}
Run Code Online (Sandbox Code Playgroud)

在您的代码中,您只在每个视图的图层上设置CATransform3D的每个部分(这就是CATransform3D矩阵的m34组件所做的).你实际上并没有在Z平面上移动它们.您可以使用转换,但我发现zPositionCALayers 的属性提供了一种更简洁的方法来定位3-D中的图层.

一旦您将图层相对于彼此放置(负值远离用户的视点),您需要将透视效果应用于主视图中托管的所有图层.为此,我发现设置sublayerTransform托管视图的图层是必要的,以便将透视图正确应用于所有托管图层.

如果您想旋转一系列图像,请使用CATransform3DRotate()主要主机视图图层的sublayerTransform.

对于一个示例应用程序,做CALayers的3-d操作,提供给他们的角度来看,看看我在文章的第二次更新链接到该项目在这里.


Jef*_*ume 2

我最终通过使用 CATransform3DMakeTranslation 解决了这个问题,这似乎是沿 z 轴向上或向下移动图层的唯一方法:

UIImageView *three = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"3.png"]];
three.layer.transform = CATransform3DMakeTranslation(0.0f, 0.0f, 20.0f);
three.center = CGPointMake(160 + 60, 240 - 60);
[self.view addSubview:three];
Run Code Online (Sandbox Code Playgroud)

(我还在 z 轴上将 UIImageView 移动了一个 -20.0f 像素。这最终达到了我想要的效果。)