iOS CATransform3D坐标 [英] iOS CATransform3D Coordinates

查看:289
本文介绍了iOS CATransform3D坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

真的很感激这方面的任何帮助。我在视图上应用了3D变换,需要识别渲染视图的边缘坐标,这样我就可以呈现与其相邻的另一个视图(没有任何像素间隙)。具体来说,我希望通过动画角度来折叠像传单一样的一系列视图(页面)。

Would really appreciate any help on this one. I have applied a 3D transformation on a view and need to identify the edge coordinates of the rendered view so I can present another view adjacent to it (without any pixels gap). Specifically I want a series of views ("pages") to fold-up like a leaflet, by animating the angle.

    int dir = (isOddNumberedPage ? 1 : -1);
    float angle = 10.0;

    theView.frame = CGRectMake(pageNumber * 320, 0, 320, 460);        
    CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
    rotationAndPerspectiveTransform.m34 = -1.0 / 2000; // Perspective
    rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 
           dir * angle / (180.0 / M_PI), 0.0f, 1.0f, 0.0f);
    theView.layer.transform = rotationAndPerspectiveTransform;

    // Now need to get the top, left, width, height of the transformed view to correct the view's left offset

我已经通过检查CALayer尝试了多种方法,尝试使用我发现的一些矩阵数学代码片段失败,但是无法破解它甚至无法获得关闭(取决于角度,好20个像素)。有没有办法我可以在不花2周的时间阅读矩阵数学教科书?

I have tried a number of ways of doing this by inspecting the CALayer, a failed attempt at using some matrix maths code snippets I found, but have not been able to crack it or even get close (depending on angle, a good 20 pixels out). Is there a way I can do this without spending 2 weeks reading a matrix maths textbook?

推荐答案

视图的框架是一个superview坐标系中的轴对齐矩形。框架完全包围视图的边界。如果视图被转换,框架会调整以紧密包围视图的新边界。

The frame of a view is an axis-aligned rectangle in the superview's coordinate system. The frame fully encloses the view's bounds. If the view is transformed, the frame adjusts to tightly enclose the view's new bounds.

当您对视图应用Y轴旋转和透视时,左右视图的边缘朝向其锚点(通常是视图的中心)移动。左边缘也变得更高或更短,而右边缘则相反。

When you apply a Y-axis rotation and perspective to a view, the left and right edges of the view move toward its anchor point (which is normally the center of the view). The left edge also grows either taller or shorter, and the right edge does the opposite.

因此视图的框架(应用转换后)会给你左边边缘坐标和变换视图的宽度,以及较高边缘的顶部和高度(可能是左边缘或右边缘)。这是我的测试代码:

So the frame of the view (after applying the transformation) will give you the left edge coordinate and the width of the transformed view, and the top and height of the taller edge (which might be either the left or right edge). Here's my test code:

NSLog(@"frame before tilting = %@", NSStringFromCGRect(self.tiltView.frame));
float angle = 30.0;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = -1.0 / 2000; // Perspective
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 
       1 * angle / (180.0 / M_PI), 0.0f, 1.0f, 0.0f);
self.tiltView.layer.transform = rotationAndPerspectiveTransform;
NSLog(@"frame after tilting = %@", NSStringFromCGRect(self.tiltView.frame));

这是输出:

2012-01-04 12:44:08.405 layer[72495:f803] frame before tilting = {{50, 50}, {220, 360}}
2012-01-04 12:44:08.406 layer[72495:f803] frame after tilting = {{62.0434, 44.91}, {190.67, 370.18}}

您还可以使用 convertPoint:fromView: convertPoint获取视图角落的坐标,在superview的坐标空间中:toView:。测试代码:

You can also get the coordinates of the corners of the view, in the superview's coordinate space using convertPoint:fromView: or convertPoint:toView:. Test code:

    CGRect bounds = self.tiltView.bounds;
    CGPoint upperLeft = bounds.origin;
    CGPoint upperRight = CGPointMake(CGRectGetMaxX(bounds), bounds.origin.y);
    CGPoint lowerLeft = CGPointMake(bounds.origin.x, CGRectGetMaxY(bounds));
    CGPoint lowerRight = CGPointMake(upperRight.x, lowerLeft.y);
#define LogPoint(P) NSLog(@"%s = %@ -> %@", #P, \
    NSStringFromCGPoint(P), \
    NSStringFromCGPoint([self.tiltView.superview convertPoint:P fromView:self.tiltView]))
    LogPoint(upperLeft);
    LogPoint(upperRight);
    LogPoint(lowerLeft);
    LogPoint(lowerRight);

输出:

2012-01-04 13:03:00.663 layer[72635:f803] upperLeft = {0, 0} -> {62.0434, 44.91}
2012-01-04 13:03:00.663 layer[72635:f803] upperRight = {220, 0} -> {252.713, 54.8175}
2012-01-04 13:03:00.663 layer[72635:f803] lowerLeft = {0, 360} -> {62.0434, 415.09}
2012-01-04 13:03:00.663 layer[72635:f803] lowerRight = {220, 360} -> {252.713, 405.182}

请注意,superview的upperLeft和upperRight点的Y坐标是不同的坐标系。

Notice that the Y coordinates of the upperLeft and upperRight points are different in the superview's coordinate system.

这篇关于iOS CATransform3D坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆