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场景仅仅是被绘制在图层的表面。