Core Animation小记(一)

2017-08-31  本文已影响0人  凯旋之歌

1. UIView 中没有暴露出来的CALayer的功能:

阴影,圆角,带颜色的边框

3D变换

非矩形范围

透明遮罩

多级非线性动画

CALayer 没有,UIView有的功能:

对CALayer进行了初步封装,调用时较便捷

UIView可以使用自动布局自适应

2.使用CA需要引入库:QuartzCore到buildPhases中

3.contents属性

你真正要赋值的类型应该是CGImageRef,它是一个指向CGImage结构的指针

layer.contents = (__bridge id)image.CGImage

UIViewContentMode

typedef enum {

UIViewContentModeScaleToFill,

UIViewContentModeScaleAspectFit,      // contents scaled to fit with fixed aspect. remainder is transparent

UIViewContentModeScaleAspectFill,     // contents scaled to fill with fixed aspect. some portion of content may be clipped.

UIViewContentModeRedraw,              // redraw on bounds change (calls -setNeedsDisplay)

UIViewContentModeCenter,              // contents remain same size. positioned adjusted.

UIViewContentModeTop,

UIViewContentModeBottom,

UIViewContentModeLeft,

UIViewContentModeRight,

UIViewContentModeTopLeft,

UIViewContentModeTopRight,

UIViewContentModeBottomLeft,

UIViewContentModeBottomRight,

} UIViewContentMode;

CALayer与之对应的为

UIViewContentModeScaleToFill -> (默认效果)

UIViewContentModeScaleAspectFit -> kCAGravityResizeAspect

UIViewContentModeScaleAspectFill ->  kCAGravityResizeAspectFill

4.UIView clipsToBounds  maskToBounds

5.contentsRect

CALayer的contentsRect属性允许我们在图层边框里显示寄宿图的一个子域

它使用了单位坐标。在app中最有趣的地方在于一个叫做image sprites(图片拼合)的

用法。图片拼合后可以打包整合到一张大图上一次性载入。相比多次载入不同的

图片,这样做能够带来很多方面的好处:内存使用,载入时间,渲染性能等等。

6.contentsCenter

contentsCenter其实是一个CGRect,它定义了一个固定的边框和一个在图

层上可拉伸的区域。他工作起来的效果和UIImage里的-resizableImageWithCapInsets:方法效果非常类似,只是它可以运用

到任何寄宿图,甚至包括在Core Graphics运行时绘制的图形

在XIB中可以使用Stretching

7.不同于UIView,当图层显示在屏幕上时,CALayer不会自动重绘它的内容。它把重绘的决定权交给了开发者。

在UIView时,当使用寄宿了视图的图层的时候,你也不必实现-displayLayer:和-方法来绘制你的寄宿图。通常做法是实现UIView的-方法,UIView就会帮你做完剩下的工作,包括在需要重绘的时候调用方法。

8.对于视图或者图层来说,并不是一个非常清晰的属性,它其实是一个虚拟属性,是根据bounds,和transform计算而来,所以当其中任何一个值发生改变,frame都会变化。相反,改变frame的值同样会影响到他们当中的值

视图的center属性和图层的position属性都指定了anchorPoint相对于父图层的位置。图层的anchorPoint通过position来控制它的frame位置,可以认为anchorPoint是用来移动图层的把柄

anchorPoint是单位坐标,指position与width,height的比例,(0.1,0.1)指position位于左10.30方向,(0.5,0.5)位于中心,(0.5,0.9)位于6点种方向。

9.zPostion属性在大多数情况下其实并不常用,可以用于在三维空间移动和旋转图层做变换,此外, 最实用的功能就是改变图层的显示顺序了。在zPostion,越大的越优先显示。不过其不能改变事件传递的顺序

10.圆角

一般使用layer.cornerRadius和masksToBounds,对全部角设置为圆角并裁剪子视图。

如果设置有些圆角有些直角,需要使用图层蒙板或是CAShapeLayer

11.阴影往往可以达到图层深度暗示的效果。也能够用来强调正在显示的图层和优先级。shadowOpacity是一个单位属性,设置一个大于0对值,阴影就可以显示在任何图层之下。shadowOpacity是一个必须在0.0(不可见)和1.0(完全不透明)之间的浮点数。想定制阴影,可以使用CAlayer的三个属性:shadowColor,shadowOffset,shadowRadius

shadowColor是CGColorRef类型

shadowOffset控制着阴影的方向和距离。它是一个CGSize值,宽度控制着阴影的横向的位移,高度控制着纵向的位移。shadowOffset默认是{0,-3},即隐形相对于Y轴有3个点点向上位移。

shadowRadius控制阴影的模糊度,当它点值时0的时候,阴影就和视图一样有一个非常明确的边界线。当值越来越大的时候,边界线看上去越来越模糊。

阴影继承自内容的外形,会连区域外的子视图的边界一起做阴影。

阴影非常耗资源,尤其有多个子图层,还有透明效果的寄宿图的时候。如果知道隐形形状时什么样子,可以制定一个shadowPath来提高性能。其时一个CGPathRef类型.

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView1;

@property (nonatomic, weak) IBOutlet UIView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//enable layer shadows

self.layerView1.layer.shadowOpacity = 0.5f;

self.layerView2.layer.shadowOpacity = 0.5f;

//create a square shadow

CGMutablePathRef squarePath = CGPathCreateMutable();

CGPathAddRect(squarePath, NULL, self.layerView1.bounds);

self.layerView1.layer.shadowPath = squarePath;

CGPathRelease(squarePath);

//create a circular shadow

CGMutablePathRef circlePath = CGPathCreateMutable();

CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds);

self.layerView2.layer.shadowPath = circlePath;

CGPathRelease(circlePath);

}

@end

但是如果是更加复杂一点的图形,UIBezierPath类会更合适

12.CALayer有一个属性叫做mask.这个属性本身就是个CALayer类型,有和其他图层一样的绘制和布局属性。它类似于一个子图层,相对于父图层(即拥有该属性的图层)布局,但是它却不是一个普通的子图层。不同于那些绘制在父图层中的子图层,mask图层定义了父图层的部分可见区域。

mask属性就像是一个饼干切割机,mask图层实心的部分会被保留下来,其他的则会被抛弃。

如果mask图层比父图层要小,只有在mask图层里面的内容才是它关心的,除此以外的一切都会被隐藏起来。

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//create mask layer

CALayer *maskLayer = [CALayer layer];

maskLayer.frame = self.layerView.bounds;

UIImage *maskImage = [UIImage imageNamed:@"Cone.png"];

maskLayer.contents = (__bridge id)maskImage.CGImage;

//apply mask to image layer

self.imageView.layer.mask = maskLayer;

}

@end

CALayer蒙板图层真正厉害的地方在于蒙板图不局限于静态图。任何有图层构成的都可以作为mask属性,这意味着你的蒙板可以通过代码甚至是动画实时生成。

13.当我们视图显示一个图片的时候,都应该正确地显示这个图片.原因如下:

能够显示最好的画质,像素既没有被压缩也没有被拉伸。

能更好的使用内存,因为这就是所有你要存储的东西。

最好的性能表现,CPU不需要为此额外的计算。

14.UIView的transform是CGAffineTransform类型,用于二维空间做旋转,缩放和平移

如下几个函数都创建了一个CGAffineTransform实例:

CGAffineTransformMakeRotation(CGFloat angle) 旋转

CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) 缩放

CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty) 平移

UIView的transform对应于CALayer的affineTransform

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;

@end

@implementation ViewController

- (void)viewDidLoad

{

       [super viewDidLoad];

//rotate the layer 45 degrees

CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_4);

self.layerView.layer.affineTransform = transform;

}

@end

Core Graphics提供了一系列的函数可以在一个变换的基础上做更深层次的变换,如果做一个既要缩放又要旋转的变换,这就会非常有用了。例如下面几个函数:

CGAffineTransformRotate(CGAffineTransform t,CGFloat angle)

CGAffineTransformScals(CGAffineTransform t, CGFloat sx, CGFloat sy)

CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)

当操纵一个变换的时候,初始生成一个什么都不做的变换很重要--也就是创建一个CGAffineTransform类型的空值,矩阵论中称作单位矩阵,Core Graphics同样也提供了一个方便的常量:

CGAffineTransformIdentity

变换的顺序会影响最终的结果,也就是说旋转之后的平移和平移之后的旋转结果可能不同。

15.CALayer的transform是CATransform3D类型,可以让图层在3D空间内移动或者旋转

Core Animation提供了一系列的方法用来创建和组合CATransform3D类型的矩阵,和Core Graphics的函数类似,但是3D的平移和旋转多出了一个z参数,并且旋转函数除了angle之外多出了x,y,z三个参数,分别决定了每个坐标轴方向上的旋转:

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

CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz)

CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)

CATransform3D的透视效果通过一个矩阵中一个很简单的元素来控制:m34。m34(图5.9)用于按比例缩放X和Y的值来计算到底要离视角多远。m34的默认值是0,我们可以通过设置m34为-1.0 /d来应用透视效果,d代表了想象中视角相机和屏幕之间的距离,以像素为单位

CALayer有一个属性叫做sublayerTransform。它也是CATransform3D类型,但和对一个图层的变换不同,它影响到所有的子图层。这意味着你可以一次性对包含这些图层的容器做变换,于是所有的子图层都自动继承了这个变换方法。

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *containerView;

@property (nonatomic, weak) IBOutlet UIView *layerView1;

@property (nonatomic, weak) IBOutlet UIView *layerView2;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

//apply perspective transform to container

CATransform3D perspective = CATransform3DIdentity;

perspective.m34 = - 1.0 / 500.0;

self.containerView.layer.sublayerTransform = perspective;

//rotate layerView1 by 45 degrees along the Y axis

CATransform3D transform1 = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);

self.layerView1.layer.transform = transform1;

//rotate layerView2 by 45 degrees along the Y axis

CATransform3D transform2 = CATransform3DMakeRotation(-M_PI_4, 0, 1, 0);

self.layerView2.layer.transform = transform2;

}

CALayer有一个叫做doubleSided的属性来控制图层的背面是否要被绘制。这是一个BOOL类型,默认为YES,如果设置为NO,那么当图层正面从相机视角消失的时候,它将不会被绘制。

尽管Core Animation图层存在于3D空间之内,但它们并不都存在同一个3D空间。每个图层的3D场景其实是扁平化的,当你从正面观察一个图层,看到的实际上由子图层创建的想象出来的3D场景,但当你倾斜这个图层,你会发现实际上这个3D场景仅仅是被绘制在图层的表面。

上一篇下一篇

猜你喜欢

热点阅读