如何理解CGAffineTransform

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何理解CGAffineTransform相关的知识,希望对你有一定的参考价值。

参考技术A CGAffineTransform实际上是一个矩阵
| a, b, 0 |
| c, d, 0 |
| tx, ty, 1 |

a=1,1 b=1,2 c=2,1 d=2,2 tx=3,1 ty=3,2
这个矩阵是用来标记这个View的变化,可以是旋转,缩放,平移。
也就是说,View的坐标为 x,y,变化后的坐标是x',y'
.
| a, b, 0 |
x',y',1=x,y,1 x | c, d, 0 |
| tx, ty, 1 |

如何跟踪连续的 CGAffineTransform 以到达屏幕上的特定点?

【中文标题】如何跟踪连续的 CGAffineTransform 以到达屏幕上的特定点?【英文标题】:How to track successive CGAffineTransforms so as to arrive at a specific point on screen? 【发布时间】:2010-12-03 03:29:03 【问题描述】:

如何在不跟踪执行的每个操作的情况下执行多个 CGAffineTransform 操作(在动画块中)?

平移操作不采用 x,y 坐标,而是采用要移位的值。因此,除非您知道当前被翻译到的位置,例如“位置 2”,否则您如何知道要转换到“位置 3”的值?

例如:

UIView 的框架位于 (0, 0) - 位置 1。我将变换设置为平移到 (768, 0) 并旋转 -90 度 - 位置 2。一段时间过去了,现在我想移动到 (768 , 1024) 并再旋转 -90 度 - 位置 3。

我如何知道从位置 2 移动到位置 3 需要翻译什么?

在上下文中,我正在尝试实现如下所示的 iPad 视图:

占据整个屏幕的 UIView 占据顶部边缘并位于 UIView 顶部的 UIToolbar 当 iPad 旋转时,UIView 与设备保持一致,但工具栏会旋转,使其始终位于屏幕的顶部边缘。

我正在使用 CGAffineTransform 平移和旋转来移动工具栏。效果很好,除非我多次旋转 iPad。第一次翻译/旋转将完美无缺。以下转换将关闭,因为我不知道要转换的正确值。

更新:

看起来如果我在 UIView.transform 结构中获取当前的翻译 (tx, ty) 值并使用它们与新位置之间的差异,它就可以工作。但是,如果视图已旋转,则此方法不起作用。由于之前的旋转,tx 和 ty 值可以翻转。我不知道如何处理。

更新 2:

做一些研究,我发现我可以从 tx, ty 获得原始的、未旋转的点,方法是获取点的 abs 值,如果 UIView 是垂直的,则可能交换 x 和 y。现在我被困在弄清楚如何以正确的顺序正确应用下一组转换。似乎无论我如何连接它们, UIView 最终都会出现在错误的位置。看起来这太复杂了,必须有更简单的方法。

【问题讨论】:

【参考方案1】:

答案显然是,您不跟踪转换。

因此,围绕屏幕旋转工具栏的方法是连接旋转和平移变换。相反,创建一个旋转变换并在动画块中设置帧。此外,基于新的 UIInterfaceOrientation,设置根据罗盘值 0、-90、-180、-270 旋转的度数。另外,根据相同的位置设置框架大小。

所以:

CGPoint portrait = CGPointMake(0, 0);
CGPoint landscapeLeft = CGPointMake(768 - 44, 0);
CGPoint landscapeRight = CGPointMake(0, 0);
CGPoint upsideDown = CGPointMake(0, 1024 - 44);

CGSize portraitSize = CGSizeMake(768, 44);
CGSize landscapeLeftSize = CGSizeMake(44, 1024);
CGSize landscapeRightSize = CGSizeMake(44, 1024);
CGSize upsideDownSize = CGSizeMake(768, 44);

CGFloat rotation;
CGRect newLocation;
switch(orientation) 
    case UIDeviceOrientationPortrait:
        NSLog(@"Changing to Portrait");
        newLocation.origin = portrait;
        newLocation.size = portraitSize;
        rotation = 0.0;
        break;

    case UIDeviceOrientationLandscapeRight:
        NSLog(@"Changing to Landscape Right");
        newLocation.origin = landscapeRight;
        newLocation.size = landscapeRightSize;
        rotation = -90.0;
        break;

    case UIDeviceOrientationLandscapeLeft:
        NSLog(@"Changing to Landscape Left");
        newLocation.origin = landscapeLeft;
        newLocation.size = landscapeLeftSize;
        rotation = -270.0;
        break;

    case UIDeviceOrientationPortraitUpsideDown:
        NSLog(@"Changing to Upside Down");
        newLocation.origin = upsideDown;
        newLocation.size = upsideDownSize;
        rotation = -180.0;
        break;

    default:
        NSLog(@"Unknown orientation: %d", orientation);
        newLocation.origin = portrait;
        newLocation.size = portraitSize;
        rotation = 0.0;
        break; 


CGRect frame = newLocation;
CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(rotation));

if(lastOrientation) 
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:.3];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationBeginsFromCurrentState:YES];


toolbar.transform = transform;
toolbar.frame = frame;

// Commit the changes
if(lastOrientation) 
    [UIView commitAnimations];


lastOrientation = orientation;

这很好用。但是,一个意想不到的问题是 iOS 代表您显示的 UI 元素的方向不正确。即,模态窗口和弹出框都保持与底层 UIView 相同的方向。这个问题使整个事情变得毫无意义。

【讨论】:

原来关于 UIPopover 方向的最后一个问题可以用 1 行来解决:[[UIApplication sharedApplication] setStatusBarOrientation:orientation animated:NO]; (但是,模态窗口仍然很古怪。)

以上是关于如何理解CGAffineTransform的主要内容,如果未能解决你的问题,请参考以下文章

如何理解FFT

如何理解工作,如何理解事业

如何理解Spring Boot中的Starter?

如何理解 CGI,WSGI

集群与分布式 如何理解(自己的理解)

JavaScript中的ArrayBuffer该如何理解呢?