为啥使用 CATransform3D 进行这种转换会减小视图的宽度?
Posted
技术标签:
【中文标题】为啥使用 CATransform3D 进行这种转换会减小视图的宽度?【英文标题】:Why is this transformation using CATransform3D reducing the view's width?为什么使用 CATransform3D 进行这种转换会减小视图的宽度? 【发布时间】:2012-01-17 02:27:28 【问题描述】:看看以下图像的进程:
这里发生的情况是,首先我选择了“棒球”,导致您看到的 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 轴折叠您的视图。 transform.m34 有什么用?我已经像这样旋转了视图,而宽度却没有改变。不知道发生了什么... 我从这篇文章中得到了转换代码:***.com/questions/347721/…。您能否提供一个代码示例来说明您如何旋转视图?如果我删除了 transform.m34 语句,那么我最终会得到如下所示的转换:cl.ly/2Z0v0P1U1T2a1p240x3L 【参考方案1】:我已经解决了。事实证明,应用CATransform3D
实际上会改变视图的框架。在我发布的代码中,当我设置视图的新框架时(因为它旋转到不同的位置),我只是在CGRectMake()
中使用view.frame.size.width
来尝试保持宽度。但是,由于CATransform3D
之前修改了宽度,我没有得到我想要的实际宽度。
解决方案是将必要的UIViews
子类化并将其原始帧存储在 ivar 中。这样,在将视图移动到不同位置时,我总是可以将其用作参考点。
【讨论】:
【参考方案2】:您不需要直接编辑 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 中的“修改转换数据结构”。以上是关于为啥使用 CATransform3D 进行这种转换会减小视图的宽度?的主要内容,如果未能解决你的问题,请参考以下文章