美文网首页
Core Animation小记(一)

Core Animation小记(一)

作者: 凯旋之歌 | 来源:发表于2017-08-31 17:30 被阅读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场景仅仅是被绘制在图层的表面。

    相关文章

      网友评论

          本文标题:Core Animation小记(一)

          本文链接:https://www.haomeiwen.com/subject/uanfjxtx.html