如何围绕Y轴翻转CALayer?

时间:2012-09-25 09:26:24

标签: ios core-animation perspective rotational-matrices

我在CALayer的子类中使用此代码,其实例是根CALayer的子层。

-(void)setSelected:(bool)s {
    selected=s;
    if (s)
    {
        CATransform3D  rot = CATransform3DMakeRotation(M_PI, 0, 1, 0);
        rot.m34=-1.0 / 200;
        [self setTransform:rot];

    }
    else
    {
            CATransform3D  rot = CATransform3DMakeRotation(0, 0, 1, 0);
        rot.m34=-1.0 / 200;
        [self setTransform:rot];
    }
}

当所选属性设置为TRUE时,会发生以下情况:旋转完成直到角度等于M_PI / 2,然后图层消失,因为它是正交的。动画的结尾是错误的:在动画的第一部分(例如在左侧)看起来增长的边缘在左侧而不是右侧结束动画。然而,内容被翻转。

我认为这与两个旋转矩阵之间的插值有关,但我无法准确理解发生了什么。

详细信息:动画看起来就像这样:

  1. 围绕Y轴增加旋转+ Pi / 2
  2. 内容翻转
  3. 围绕Y轴增加-Pi / 2的旋转,就好像它被(yz)平面反弹一样
  4. 翻转的内容是我想要实现的目标。

    以下是我得到的动画帧。如你所见,梯形的小边始终在左边;它应该在动画结尾的右侧(右上方框架)。 A layer rotating around the Y-axis

2 个答案:

答案 0 :(得分:6)

变换的数学运算不正确。您应该在旋转变换后应用透视变换,这意味着连接两个变换。更改旋转变换的m34系数不等效。

您应该通过以下方式替换您的代码:

-(void)setSelected:(bool)s {
    selected=s;
    CATransform3D perpectiveTransform = CATransform3DIdentity;
    perpectiveTransform.m34 =-1.0 / 200;

    if (s)
    {

        CATransform3D  rot = CATransform3DMakeRotation(M_PI, 0, 1, 0);
        [self setTransform:CATransform3DConcat(rot, perpectiveTransform)];

    }
    else
    {
        CATransform3D  rot = CATransform3DMakeRotation(0, 0, 1, 0);
        [self setTransform:CATransform3DConcat(rot, perpectiveTransform)];
    }
}

顺便说一下,应用透视变换的一种更方便的方法是使用超层的sublayerTransform属性,从而将其应用于每个子层(如果需要)。

这会产生类似的结果:

self.superlayer.sublayerTransform = perspectiveTransform;  //do this in your setup
....
self.transform = rot;

获得相同的结果。

答案 1 :(得分:0)

想象一下,你的图层是一块半透明的塑料,上面投射着一个图像,因此它会照射到两侧。在pi / 2的旋转时,它是边缘开启的,因此它消失了。当您的旋转大于pi / 2但小于pi时,平板塑料的背面会暴露出来。因为它是半透明的,你可以看到图像的背面,但是因为你从后面看到它,所以它是镜像的。当角度达到pi时,纸张在y轴上翻转整整180度。它是倒置的,你可以看到后面的图像,所以它是向后的。