如何理解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的主要内容,如果未能解决你的问题,请参考以下文章