IOS Core Animation Advanced Techniques的学习笔记(四)

第五章:Transforms

Affine Transforms

CGAffineTransform是二维的

Creating a CGAffineTransform

主要有三种变化方法

旋转:

CGAffineTransformMakeRotation(CGFloat angle)

缩放:

CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)

移动:

CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)

例子5.1 CGAffineTransformMakeRotation

源码在这里下载:http://www.informit.com/title/9780133440751

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *layerView;
  3. @end
  4. @implementation ViewController
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. //rotate the layer 45 degrees
  9. CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_4);
  10. self.layerView.layer.affineTransform = transform;
  11. }
  12. @end

修改 CGAffineTransformMakeScale

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //rotate the layer 45 degrees
  5. CGAffineTransform transform = CGAffineTransformMakeScale(0.5, 0.5);
  6. self.layerView.layer.affineTransform = transform;
  7. }

修改   CGAffineTransformMakeTranslation

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //rotate the layer 45 degrees
  5. CGAffineTransform transform = CGAffineTransformMakeTranslation(-50.0, 30.0);
  6. self.layerView.layer.affineTransform = transform;
  7. }

Combining Transforms

方法1:使用CGAffineTransformConcat

继续修改例子5.1

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //rotate the layer 45 degrees
  5. CGAffineTransform transform1 = CGAffineTransformMakeRotation(M_PI_4);
  6. CGAffineTransform transform2 = CGAffineTransformMakeScale(0.5, 0.5);
  7. CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
  8. self.layerView.layer.affineTransform = transform;
  9. }

方法2:

CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)

和前面的CGAffineTransformMakeRotation函数相同,也可以混用

CGAffineTransform t可以使用CGAffineTransformIdentity函数初始化

例子5.2

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *layerView;
  3. @end
  4. @implementation ViewController
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. //create a new transform
  9. CGAffineTransform transform = CGAffineTransformIdentity;
  10. //scale by 50%
  11. transform = CGAffineTransformScale(transform, 0.5, 0.5);
  12. //rotate by 30 degrees
  13. transform = CGAffineTransformRotate(transform, M_PI / 180.0 * 30.0);
  14. //translate by 200 points
  15. transform = CGAffineTransformTranslate(transform, 200, 0);
  16. //apply transform to layer
  17. self.layerView.layer.affineTransform = transform;
  18. }
  19. @end

下面记几个特殊值

1. 首先要知道函数 CGAffineTransformIdentity 初始化的结果

2. 左右翻转

CGAffineTransformMake(-1,0,0,1,0,0);


3. 以右边为轴向右翻转

CGAffineTransformMake(-1,0,0,1,self.layerView.frame.size.width,0);

4. 上下翻转

CGAffineTransformMake(1,0,0, -1,0,0);

5. 以底边为轴向下翻转

CGAffineTransformMake(1,0,0, -1,0,self.layerView.frame.size.height);

6. 转180°

CGAffineTransformMake(-1,0,0, -1,0,0);

7. 例子5.3,向右斜拉

CGAffineTransformMake(1,0, -1,1,0,0);

代码:

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *layerView;
  3. @end
  4. @implementation ViewController
  5. CGAffineTransform CGAffineTransformMakeShear(CGFloat x, CGFloat y)
  6. {
  7. CGAffineTransform transform = CGAffineTransformIdentity;
  8. transform.c = -x;
  9. transform.b = y;
  10. return transform;
  11. }
  12. - (void)viewDidLoad
  13. {
  14. [super viewDidLoad];
  15. //shear the layer at a 45-degree angle
  16. self.layerView.layer.affineTransform = CGAffineTransformMakeShear(1, 0);
  17. }
  18. @end

8. 例子5.3,向左斜拉

CGAffineTransformMake(1, 0,1, 1, 0, 0);

3D Transforms

类似CGAffineTransform,CATransform3D是三维的

CATransform3D又是一个结构。他有自己的一个公式,可以进行套用。

struct CATransform3D

{

CGFloat     m11(x缩放),    m12(y切变),    m13(旋转),     m14( );

CGFloat     m21(x切变),    m22(y缩放),    m23( ),           m24( );

CGFloat     m31(旋转),      m32( ),           m33( ),            m34(透视效果,要操作的这个对象要有旋转的角度,否则没有效果。正直/负值都有意义);

CGFloat     m41(x平移),    m42(y平移),    m43(z平移),    m44( );

};

同样有三种变换方法

旋转:

CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z)

首先要先清楚x,y,z是什么

{x, y, z}组成的向量就是旋转要使用的轴,angle是旋转角度

例:原图

向X轴旋转45度。                               向Y轴旋转45度。                         向Z轴旋转45度。

    

向 X轴,Y轴都旋转45度,就是沿着对角线旋转。

缩放:

CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz)

sx:X轴缩放,代表一个缩放比例,一般都是0 ---1之间的数字。

sy:Y轴缩放。

sz:整体比例变换时,也就是m11(sx) == m22(sy)时,若m33(sz)>1,图形整体缩小,

若0 < m33(sz) < 1,图形整体放大,

若m33(sz) < 0,发生关于原点的对称等比变换。

当sx = 1,sy =1时。如图:

当sx = 0.5,sy =0.5时。如图:

变换:

CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)

t‘ = [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1]

1    0    0    0

0    1    0    0

0    0    1    0

tx   ty    tz   1

竖起来看对应前面的数据结构就很明显了。

tx:X轴偏移位置,往下为正数。

ty:Y轴偏移位置,往右为正数。

tz:Z轴偏移位置,往外为正数。

可以通过直接修改数据结构,来设置变换效果

struct CATransform3D

{

CGFloat m11, m12, m13, m14;

CGFloat m21, m22, m23, m24;

CGFloat m31, m32, m33, m34;

CGFloat m41, m42, m43, m44;

}

[objc] view plaincopyprint?

  1. CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);
  2. transform.m11 = 2;

或者修改键值

[objc] view plaincopyprint?

  1. [myLayer setValue:[NSNumber numberWithInt:0] forKeyPath:@"transform.rotation.x"];

例子5.4

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *layerView;
  3. @end
  4. @implementation ViewController
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. //rotate the layer 45 degrees along the Y axis
  9. CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);
  10. self.layerView.layer.transform = transform;
  11. }
  12. @end

修改例子5.4,修改自http://lepetit-prince.net/ios/?p=451

[objc] view plaincopyprint?

  1. #import "ViewController.h"
  2. #import <QuartzCore/QuartzCore.h>
  3. @interface ViewController ()
  4. {
  5. BOOL front;
  6. }
  7. @property (nonatomic, weak) IBOutlet UIView *layerView;
  8. @end
  9. @implementation ViewController
  10. - (void)viewDidLoad
  11. {
  12. [super viewDidLoad];
  13. front = YES;
  14. self.layerView.layer.contents = (__bridge id)([UIImage imageNamed:@"front.png"].CGImage);
  15. }
  16. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  17. {
  18. [UIView animateWithDuration:0.5 animations:^{
  19. self.layerView.layer.transform = CATransform3DMakeRotation(M_PI * 0.5, 0.0f, 1.0f, 0.0f);
  20. } completion:^(BOOL finished) {
  21. self.layerView.layer.transform = CATransform3DMakeRotation(M_PI * 1.5, 0.0f, 1.0f, 0.0f);
  22. self.layerView.layer.contents = front ? (__bridge id)([UIImage imageNamed:@"back.png"].CGImage) : (__bridge id)([UIImage imageNamed:@"front.png"].CGImage);
  23. [UIView animateWithDuration:0.5 animations:^{
  24. self.layerView.layer.transform = CATransform3DMakeRotation(M_PI * 2, 0.0f, 1.0f, 0.0f);
  25. } completion:^(BOOL finished) {
  26. front = !front;
  27. }];
  28. }];
  29. }
  30. @end

资源文件 front.png   back.png

Perspective Projection

前面提到过m34(透视效果,要操作的这个对象要有旋转的角度,否则没有效果。正直/负值都有意义)

例子5.5

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *layerView;
  3. @end
  4. @implementation ViewController
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. //create a new transform
  9. CATransform3D transform = CATransform3DIdentity;
  10. //apply perspective
  11. transform.m34 = - 1.0 / 500.0;
  12. //rotate by 45 degrees along the Y axis
  13. transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);
  14. //apply to layer
  15. self.layerView.layer.transform = transform;
  16. }
  17. @end

如果修改注释掉旋转,看看会有什么结果

[objc] view plaincopyprint?

  1. //rotate by 45 degrees along the Y axis
  2. //transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);

例子是用的透视场景是±1.0/d,d镜头到景物的距离,取值500~1000效果最好,±代表方向

The Vanishing Point

当景物慢慢远离镜头时,随着越来越小最终聚集到一点就是Vanishing Point(灭点)

通常情况灭点是在视图的正中心,或者在包含所有景物范围的中心。

Core Animation把灭点定义在anchorPoint,所以在变换前需要确定anchorPoint,

尤其需要注意,3D变换时最好确保同一视图内的所有layey有相同的灭点

The sublayerTransform Property

如果你有多个View或Layer有相同的3D变换,就可以使用sublayerTransform,

sublayerTransform也是CATransform3D,只有sublayers才会响应。

默认值是Identity Transform(CATransform3DIdentity)

例子5.6

[objc] view plaincopyprint?

  1. @interface ViewController ()
  2. @property (nonatomic, weak) IBOutlet UIView *containerView;
  3. @property (nonatomic, weak) IBOutlet UIView *layerView1;
  4. @property (nonatomic, weak) IBOutlet UIView *layerView2;
  5. @end
  6. @implementation ViewController
  7. - (void)viewDidLoad
  8. {
  9. [super viewDidLoad];
  10. //apply perspective transform to container
  11. CATransform3D perspective = CATransform3DIdentity;
  12. perspective.m34 = - 1.0 / 500.0;
  13. self.containerView.layer.sublayerTransform = perspective;
  14. //rotate layerView1 by 45 degrees along the Y axis
  15. CATransform3D transform1 = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);
  16. self.layerView1.layer.transform = transform1;
  17. //rotate layerView2 by 45 degrees along the Y axis
  18. CATransform3D transform2 = CATransform3DMakeRotation(-M_PI_4, 0, 1, 0);
  19. self.layerView2.layer.transform = transform2;
  20. }
  21. @end

我们挪动一下xib里的图片位置:

再看结果

恢复xib文件,并修改代码

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //apply perspective transform to container
  5. //    CATransform3D perspective = CATransform3DIdentity;
  6. //    perspective.m34 = - 1.0 / 500.0;
  7. //    self.containerView.layer.sublayerTransform = perspective;
  8. //apply perspective
  9. CATransform3D transform1 = CATransform3DIdentity;
  10. transform1.m34 = - 1.0 / 500.0;
  11. transform1 = CATransform3DRotate(transform1, M_PI_4, 0, 1, 0);
  12. self.layerView1.layer.transform = transform1;
  13. //rotate layerView2 by 45 degrees along the Y axis
  14. CATransform3D transform2 = CATransform3DIdentity;
  15. transform2.m34 = - 1.0 / 500.0;
  16. transform2 = CATransform3DRotate(transform2, -M_PI_4, 0, 1, 0);
  17. self.layerView2.layer.transform = transform2;
  18. }

结果和最初一样,但再次修改xib文件,挪动图片看结果,比较未改代码时的效果

大家发现设置sublayerTransform的好处了吗

1. 可以一次设置所有subLayer的变换效果

2. Vanishing Point(灭点)被同时设置在container layer即父图层的中心,这就意味着无论你怎么

修改subLayer的position或frame,它们都会保持一个相同的灭点。

Backfaces

例子5.4,我们设置的是旋转M_PI_4(45°),改为M_PI(180°)

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //rotate the layer 45 degrees along the Y axis
  5. CATransform3D transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
  6. self.layerView.layer.transform = transform;
  7. }

翻到了layer背面,显示的是原图像的镜像图。由此可见layer是双面的,并且两面都被描绘了。

因此我们会想到,为什么要浪费GPU去描绘我们看不见的部分呢。CALayer的另外一个属性

doubleSided可以解决这个问题。

在刚才修改过的例子5.4的代码中增加doubleSided设置

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //rotate the layer 45 degrees along the Y axis
  5. CATransform3D transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
  6. self.layerView.layer.transform = transform;
  7. self.layerView.layer.doubleSided = NO;
  8. }


图像没有了

Layer Flattening

自己看例子吧,例子5.7和5.8

Solid Objects

也自己看例子吧,例子5.9和5.10

时间: 2024-10-22 23:42:01

IOS Core Animation Advanced Techniques的学习笔记(四)的相关文章

IOS Core Animation Advanced Techniques的学习笔记(一)

转载. Book Description Publication Date: August 12, 2013 Core Animation is the technology underlying Apple’s iOS user interface. By unleashing the full power of Core Animation, you can enhance your app with impressive 2D and 3D visual effects and creat

IOS Core Animation Advanced Techniques的学习笔记(五)

第六章:Specialized Layers   类别 用途 CAEmitterLayer 用于实现基于Core Animation粒子发射系统.发射器层对象控制粒子的生成和起源 CAGradientLayer 用于绘制一个颜色渐变填充图层的形状(所有圆角矩形边界内的部分) CAEAGLLayer/CAOpenGLLayer 用于设置需要使用OpenGL ES(iOS)或OpenGL(OS X)绘制的内容与内容储备. CAReplicatorLayer 当你想自动生成一个或多个子层的拷贝.复制器

IOS Core Animation Advanced Techniques的学习笔记(二)

[objc] view plaincopyprint?转载学习 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx { CGFloat width = 10.0f; //draw a thick red circle CGContextSetLineWidth(ctx, width); CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor); CG

IOS Core Animation Advanced Techniques的学习笔记(三)

第四章:Visual Effects   Rounded Corners 例子4.1 cornerRadius 源码在这里下载:http://www.informit.com/title/9780133440751 [objc] view plaincopyprint? #import "ViewController.h" #import <QuartzCore/QuartzCore.h> @interface ViewController () @property (no

iOS Core Animation Advanced Techniques(四):隐式动画和显式动画

隐式动画 按照我的意思去做,而不是我说的. -- 埃德娜,辛普森 我们在第一部分讨论了Core Animation除了动画之外可以做到的任何事情.但是动画师Core Animation库一个非常显著的特性.这一章我们来看看它是怎么做到的.具体来说,我们先来讨论框架自动完成的隐式动画(除非你明确禁用了这个功能). 事务 Core Animation基于一个假设,说屏幕上的任何东西都可以(或者可能)做动画.动画并不需要你在Core Animation中手动打开,相反需要明确地关闭,否则他会一直存在.

iOS Core Animation Advanced Techniques(六): 基于定时器的动画和性能调优

基于定时器的动画 我可以指导你,但是你必须按照我说的做. -- 骇客帝国 在第10章“缓冲”中,我们研究了CAMediaTimingFunction,它是一个通过控制动画缓冲来模拟物理效果例如加速或者减速来增强现实感的东西,那么如果想更加真实地模拟 物理交互或者实时根据用户输入修改动画改怎么办呢?在这一章中,我们将继续探索一种能够允许我们精确地控制一帧一帧展示的基于定时器的动画. 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显

iOS Core Animation Advanced Techniques(三):专用图层

到目前为止,我们已经探讨过CALayer类了,同时我们也了解到了一些非常有用的绘图和动画功能.但是Core Animation图层不仅仅能作用于图片和颜色而已.本章就会学习其他的一些图层类,进一步扩展使用Core Animation绘图的能力. CAShapeLayer 在第四章『视觉效果』我们学习到了不使用图片的情况下用CGPath去构造任意形状的阴影.如果我们能用同样的方式创建相同形状的图层就好了. CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类.你指定诸如颜色

iOS Core Animation Advanced Techniques(七):高效绘图、图像IO以及图层性能

高效绘图不必要的效率考虑往往是性能问题的万恶之源. ——William Allan Wulf 在第12章『速度的曲率』我们学习如何用Instruments来诊断Core Animation性能问题.在构建一个iOS app的时候会遇到很多潜在的性能陷阱,但是在本章我们将着眼于有关绘制的性能问题. 软件绘图 术语绘图通常在Core Animation的上下文中指代软件绘图(意即:不由GPU协助的绘图).在iOS中,软件绘图通常是由Core Graphics框架完成来完成.但是,在一些必要的情况下,

iOS Core Animation Advanced Techniques(二):视觉效果和变换

四)视觉效果 嗯,园和椭圆还不错,但如果是带圆角的矩形呢? 我们现在能做到那样了么? 史蒂芬·乔布斯 我们在第三章『图层几何学』中讨论了图层的frame,第二章『寄宿图』则讨论了图层的寄宿图.但是图层不仅仅可以是图片或是颜色的容器:还有一系列内建的特性使得创造美丽优雅的令人深刻的界面元素成为可能.在这一章,我们将会探索一些能够通过使用CALayer属性实现的视觉效果. 圆角 圆角矩形是iOS的一个标志性审美特性.这在iOS的每一个地方都得到了体现,不论是主屏幕图标,还是警告弹框,甚至是文本框.按