为什么使用CATransform3D进行变换会减小视图的宽度?

5
请看以下图像的进程:

enter image description here enter image description here enter image description here 这里发生的是我首先选择了“棒球”,导致您看到的3个灰色视图向左旋转,以便其中一个带有各种级别的视图处于中间位置(第二张图片)。从此时可以看出,视图的宽度已大大缩小。第三张图片在点击包含运动名称的视图后发生,导致其旋转回到中间。
据我所知,当视图旋转到中间位置时,其宽度会减小。但我不知道为什么会这样。
以下是相关代码。pos 表示要放置的 view 位置。 0 表示它在中间,1 表示它在中间的右边,-1 表示它在中间的左边等。
- (void)perspectiveView:(MenuSection *)view forPosition:(NSInteger)pos
{

    CALayer *layer = view.layer;
    CATransform3D transform = CATransform3DIdentity;

    MenuSection *prevView = (pos >= 0) ? (MenuSection *)[self viewWithTag:view.tag - 1] : (MenuSection *)[self viewWithTag:view.tag + 1];

    if (pos == 0) {
        view.changingToFrame = CGRectMake(round((480 - view.frame.size.width)/2), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
        view.frame = view.changingToFrame;

    } else {

        if (pos == 1) {
            NSLog(@"%@",NSStringFromCGRect(prevView.changingToFrame));
            view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x + prevView.frame.size.width + 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
            transform.m34 = 1.0 / 1000;
        } else if (pos == -1){
            view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x - view.frame.size.width - 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
            transform.m34 = 1.0 / -1000;
        } else if (pos == 2){
            view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x + prevView.frame.size.width + 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
            transform.m34 = 1.0 / 500;
        } else if (pos == -2){
            view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x - view.frame.size.width - 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
            transform.m34 = 1.0 / -500;
        }

        view.frame = view.changingToFrame;

        transform = CATransform3DRotate(transform, 45.0f * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
    }

    layer.transform = transform;
}

我通过添加非常微小的Z轴变换来解决了这个问题。这并不总是有效的,如果操作不当,会使您的视图沿着y=x轴折叠。 - CodaFi
transform.m34是用来做什么的?我已经旋转了视图,但宽度从未改变过。不确定发生了什么... - bentford
我从这篇文章中获取了变换代码:https://dev59.com/ynRC5IYBdhLWcg3wSu97。你能提供一个旋转视图的代码示例吗?如果我删除transform.m34语句,那么最终得到的变换看起来像这样:http://cl.ly/2Z0v0P1U1T2a1p240x3L - maxedison
2个回答

7
我已经解决了这个问题。原来应用 CATransform3D 实际上会改变视图的框架。在我发布的代码中,当我设置视图的新框架(因为它旋转到不同的位置)时,我只是使用 view.frame.size.widthCGRectMake() 中试图保持宽度。但是,由于 CATransform3D 先前修改了宽度,所以我得不到实际想要的宽度。
解决方法是对必要的 UIViews 进行子类化,并将它们的原始框架存储在一个实例变量中。这样,当移动视图到不同的位置时,我可以始终使用它作为参考点。

0

您不需要直接编辑CATransform3D矩阵(m34等)来实现此效果。请尝试以下方法:

if (pos == 0) {
     view.changingToFrame = CGRectMake(round((480 - view.frame.size.width)/2), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
    view.frame = view.changingToFrame;
} else {
    if (pos == 1) {
         view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x + prevView.frame.size.width + 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
        transform = CATransform3DRotate(transform, M_PI/4.0f, 0.0f, 1.0f, 0.0f);
    } else if (pos == -1){
        view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x - view.frame.size.width - 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
        transform = CATransform3DRotate(transform, -M_PI/4.0f, 0.0f, 1.0f, 0.0f);
    } else if (pos == 2){
        view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x + prevView.frame.size.width + 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
        transform = CATransform3DRotate(transform, M_PI/3.0f, 0.0f, 1.0f, 0.0f);
    } else if (pos == -2){
        view.changingToFrame = CGRectMake(round(prevView.changingToFrame.origin.x - view.frame.size.width - 20), view.frame.origin.y, view.frame.size.width, view.frame.size.height);
        transform = CATransform3DRotate(transform, -M_PI/3.0f, 0.0f, 1.0f, 0.0f);
    }
    view.frame = view.changingToFrame;
}
layer.transform = transform;

然后调整这些角度,直到看起来合适。


如果您想要透视效果,必须直接修改 m34。请参阅 Core Animation Programming Guide 中的“修改变换数据结构”部分。 - rob mayoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接