CALayer这些牛逼的子类你造吗_补全篇

之前讲到几个常用的CALayer的子类,对对对,就是他:iOS动画篇_CALayer这些牛逼的子类你造吗。今天我们来讲其他几个吧,要不然,我不说你是不是以为我不会!!!

那我们今天就从一个比较酷炫的开始:

CATransformLayer

我们先看一下系统有没有像之前讲过的几个子类一样,给它一些特殊的属性或者方法:

@interface CATransformLayer : CALayer
@end

啥都没有,我擦嘞,但是上面好像有一段描述我们看一下:

/* "Transform" layers are used to create true 3D layer hierarchies.
 *
 * Unlike normal layers, transform layers do not project (i.e. flatten)
 * their sublayers into the plane at Z=0. However due to this neither
 * do they support many features of the 2D compositing model:
 *
 * - only their sublayers are rendered (i.e. no background, contents,
 *   border)
 *
 * - filters, backgroundFilters, compositingFilter, mask, masksToBounds
 *   and shadow related properties are ignored (they all assume 2D
 *   image processing of the projected layer)
 *
 * - opacity is applied to each sublayer individually, i.e. the transform
 *   layer does not form a compositing group.
 *
 * Also, the -hitTest: method should never be called on transform
 * layers (they do not have a 2D coordinate space into which to map the
 * supplied point.) CALayer will pass over transform layers directly to
 * their sublayers, applying the effects of the transform layer's
 * geometry when hit-testing each sublayer. */

我们从中可以看出它作为父Layer时,对他的sublayers会有3D效果,也就是说不平面化它的子图层,大家一提到3D效果,就会想到一个神奇的东西景深,先说一下景深是个什么东西,提到景深,那我们就一定要说CATransform3D,它定义了一个4x4 的 CGFloat值的矩阵,就是这样的:

struct CATransform3D
{
  CGFloat m11, m12, m13, m14;
  CGFloat m21, m22, m23, m24;
  CGFloat m31, m32, m33, m34;
  CGFloat m41, m42, m43, m44;
}

其中的m34,就是上面提到的景深效果的源头,我们写一段代码看一下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    CALayer *layer_ = [CALayer layer];
    layer_.bounds = CGRectMake(0, 0, 100, 100);
    layer_.position = CGPointMake(self.view.center.x, 200);
    layer_.opacity = 0.6;
    layer_.backgroundColor = [UIColor redColor].CGColor;
    layer_.borderWidth = 5;
    layer_.borderColor = [[UIColor greenColor] colorWithAlphaComponent:0.4].CGColor;
    layer_.cornerRadius = 20;
    layer_.masksToBounds = YES;
    [self.view.layer addSublayer:layer_];
    //
    CATransform3D fromValue_ = CATransform3DIdentity;
    fromValue_ = CATransform3DRotate(fromValue_, M_PI_2 / 2, 0, 1, 0);
    layer_.transform = fromValue_;
    
    CALayer *layer = [CALayer layer];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.position = self.view.center;
    layer.opacity = 0.6;
    layer.backgroundColor = [UIColor blueColor].CGColor;
    layer.borderWidth = 5;
    layer.borderColor = [[UIColor orangeColor] colorWithAlphaComponent:0.4].CGColor;
    layer.cornerRadius = 20;
    layer.masksToBounds = YES;
    [self.view.layer addSublayer:layer];
    //
    CATransform3D fromValue = CATransform3DIdentity;
    fromValue.m34 = 1.0 / -500;
    fromValue = CATransform3DRotate(fromValue, M_PI_2 / 2, 0, 1, 0);
    layer.transform = fromValue;
}

运行结果:



是不是明显发现蓝色的layer3D效果更强烈一些。
下面我们试一下这样的代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    CALayer *layer = [CALayer layer];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.opacity = 0.6;
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.borderWidth = 5;
    layer.borderColor = [[UIColor greenColor] colorWithAlphaComponent:0.4].CGColor;
    layer.cornerRadius = 20;
    layer.masksToBounds = YES;
    
    CALayer *layer_2 = [CALayer layer];
    layer_2.bounds = CGRectMake(0, 0, 100, 100);
    layer_2.opacity = 0.6;
    layer_2.backgroundColor = [UIColor blueColor].CGColor;
    layer_2.borderWidth = 5;
    layer_2.borderColor = [[UIColor orangeColor] colorWithAlphaComponent:0.4].CGColor;
    layer_2.cornerRadius = 20;
    layer_2.masksToBounds = YES;
    //
    CALayer *containerLayer = [CALayer layer];
    containerLayer.bounds = CGRectMake(0, 0, 100, 100);
    containerLayer.position = self.view.center;
    layer.position = CGPointMake(50, 50);
    layer_2.position = CGPointMake(50, 50);
    [containerLayer addSublayer:layer];
    [containerLayer addSublayer:layer_2];
    [self.view.layer addSublayer:containerLayer];
    //
    CATransform3D containerTransform = CATransform3DIdentity;
    containerTransform.m34 = -1.0 / 500.0;
    containerLayer.transform = containerTransform;
    //
    CATransform3D fromValue = CATransform3DIdentity;
    fromValue = CATransform3DRotate(fromValue, M_PI_2, 0, 1, 0);
    fromValue = CATransform3DTranslate(fromValue, 0, 0, -10);
    layer.transform = fromValue;
    
    CATransform3D fromValue_2 = CATransform3DIdentity;
    fromValue_2 = CATransform3DRotate(fromValue_2, M_PI_2, 0, 1, 0);
    fromValue_2 = CATransform3DTranslate(fromValue_2, 0, 0, -50);
    layer_2.transform = fromValue_2;
}

运行结果,一片空白,啥都没有。

我们做一处改动:

CATransformLayer *containerLayer = [CATransformLayer layer];

运行结果:


⚠️:所以有人说CATransformLayer便是给他的子图层添加了景深的效果。瞎搞,把设置景深的代码containerTransform.m34 = -1.0 / 500.0;去掉,运行,你会发现还是一片空白。这就说明CATransformLayer并不是这么个作用。那这个东西的特殊之处究竟是什么呢?
其实就是上面说的:CATransformLayer并不平面化它的子图层,所以它能够用于构造一个层级分明的3D结构。
上代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    CALayer *layer = [CALayer layer];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.opacity = 0.6;
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.borderWidth = 5;
    layer.borderColor = [[UIColor greenColor] colorWithAlphaComponent:0.4].CGColor;
    layer.cornerRadius = 20;
    layer.masksToBounds = YES;

    CALayer *containerLayer = [CALayer layer];
    containerLayer.bounds = CGRectMake(0, 0, 100, 100);
    containerLayer.position = self.view.center;
    layer.position = CGPointMake(50, 50);
    layer_2.position = CGPointMake(50, 50);
    [containerLayer addSublayer:layer];
    [self.view.layer addSublayer:containerLayer];

    CATransform3D containerTransform = CATransform3DIdentity;
    containerLayer.transform = containerTransform;

    CATransform3D fromValue = CATransform3DIdentity;
    fromValue = CATransform3DRotate(fromValue, M_PI_2, 0, 1, 0);
    layer.transform = fromValue;
}

运行结果:不出所料,一片空白。
于是,我们把containerLayerCALayer改成CATransformLayer ,结果,还是一片空白。
现在,你肯定觉的我也是在扯淡,下面精彩的部分来了:
我们给containerLayer添加一个新的transform,代码也就是这样的:

- (void)viewDidLoad {
    [super viewDidLoad];
    CALayer *layer = [CALayer layer];
    layer.bounds = CGRectMake(0, 0, 100, 100);
    layer.opacity = 0.6;
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.borderWidth = 5;
    layer.borderColor = [[UIColor greenColor] colorWithAlphaComponent:0.4].CGColor;
    layer.cornerRadius = 20;
    layer.masksToBounds = YES;

    CALayer *containerLayer = [CALayer layer];
    containerLayer.bounds = CGRectMake(0, 0, 100, 100);
    containerLayer.position = self.view.center;
    layer.position = CGPointMake(50, 50);
    layer_2.position = CGPointMake(50, 50);
    [containerLayer addSublayer:layer];
    [self.view.layer addSublayer:containerLayer];

    CATransform3D containerTransform = CATransform3DIdentity;
    //看这,我是新加的
    containerTransform = CATransform3DRotate(containerTransform, M_PI_2, 0, 1, 0);
    //
    containerLayer.transform = containerTransform;

    CATransform3D fromValue = CATransform3DIdentity;
    fromValue = CATransform3DRotate(fromValue, M_PI_2, 0, 1, 0);
    layer.transform = fromValue;
}

运行结果:


现在,我们再把containerLayerCATransformLayer改成CALayer ,结果,一片空白!你是不是明白了呢?其实还是上面那句话!
我们利用它来做一个立方体:

#import "ViewController.h"

@interface ViewController (){
    CGPoint startPoint;
    CATransformLayer *s_Cube;
    float pix, piy;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //
    CATransform3D c1t = CATransform3DIdentity;
    CALayer *cube1 = [self cubeWithTransform:c1t];
    s_Cube = (CATransformLayer *)cube1;
    [self.view.layer addSublayer:cube1];
}
- (CALayer *)faceWithTransform:(CATransform3D)transform color:(UIColor*)color
{
    CALayer *face = [CALayer layer];
    face.frame = CGRectMake(-50, -50, 100, 100);
    face.backgroundColor = color.CGColor;
    face.transform = transform;
    return face;
}

- (CALayer *)cubeWithTransform:(CATransform3D)transform
{
    //容器
    CATransformLayer *cube = [CATransformLayer layer];
    
    //前
    CATransform3D ct = CATransform3DMakeTranslation(0, 0, 50);
    [cube addSublayer:[self faceWithTransform:ct color:[UIColor redColor]]];
    
    //右
    ct = CATransform3DMakeTranslation(50, 0, 0);
    ct = CATransform3DRotate(ct, M_PI_2, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct color:[UIColor yellowColor]]];
    
    //上
    ct = CATransform3DMakeTranslation(0, -50, 0);
    ct = CATransform3DRotate(ct, M_PI_2, 1, 0, 0);
    [cube addSublayer:[self faceWithTransform:ct color:[UIColor blueColor]]];
    
    //下
    ct = CATransform3DMakeTranslation(0, 50, 0);
    ct = CATransform3DRotate(ct, -M_PI_2, 1, 0, 0);
    [cube addSublayer:[self faceWithTransform:ct color:[UIColor brownColor]]];
    
    //左
    ct = CATransform3DMakeTranslation(-50, 0, 0);
    ct = CATransform3DRotate(ct, -M_PI_2, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct color:[UIColor greenColor]]];
    
    //后
    ct = CATransform3DMakeTranslation(0, 0, -50);
    ct = CATransform3DRotate(ct, M_PI, 0, 1, 0);
    [cube addSublayer:[self faceWithTransform:ct color:[UIColor orangeColor]]];
    
    //
    CGSize containerSize = self.view.bounds.size;
    cube.position = CGPointMake(containerSize.width / 2.0,
                                containerSize.height / 2.0);
    
    cube.transform = transform;
    return cube;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    startPoint = [touch locationInView:self.view];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint currentPosition = [touch locationInView:self.view];
    CGFloat deltaX = startPoint.x - currentPosition.x;
    CGFloat deltaY = startPoint.y - currentPosition.y;
    CATransform3D c1t = CATransform3DIdentity;
    c1t = CATransform3DRotate(c1t, pix + M_PI_2 * deltaY / 100, 1, 0, 0);
    c1t = CATransform3DRotate(c1t, piy - M_PI_2 * deltaX / 100, 0, 1, 0);
    s_Cube.transform = c1t;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint currentPosition = [touch locationInView:self.view];
    CGFloat deltaX = startPoint.x - currentPosition.x;
    CGFloat deltaY = startPoint.y - currentPosition.y;
    pix = M_PI_2 * deltaY / 100;
    piy = -M_PI_2 * deltaX / 100;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

运行结果:

如果针对上面的解释你还不是很理解,那么你可以把这个立方体的CATransformLayer换成CALayer,试试看喽。


CAReplicatorLayer

通过这个名字,我就确定它和图层复制有关,你信不信?
我们看一下系统提供的API:

@interface CAReplicatorLayer : CALayer
@property NSInteger instanceCount; //复制图层的个数,包括加到上面的
@property BOOL preservesDepth; // 子图层是否平面化(看上面那个CATransformLayer)
@property CFTimeInterval instanceDelay; // 复制层动画延迟时间
@property CATransform3D instanceTransform; //子图层的transform变换,一般用来决定复制图层的初始位置以及初始试图变换
@property(nullable) CGColorRef instanceColor; // 复制层颜色,该颜色是与本体元素色值相乘,鬼知道是什么颜色
@property float instanceRedOffset; // 复制层红色偏移量
@property float instanceGreenOffset; // 复制层绿色偏移量
@property float instanceBlueOffset; // 复制层蓝色偏移量
@property float instanceAlphaOffset; // 复制层透明度偏移量
@end

属性虽少,变化很大,主要是于核心动画的强强联合,他就有无限的可能性,三种效果,您上眼:
NO.1:深夜电台广播

-(void)lineWave{
    CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
    replicatorLayer.bounds = self.view.frame;
    replicatorLayer.position = self.view.center;
    [self.view.layer addSublayer:replicatorLayer];
    //
    CALayer *layer = [CALayer layer];
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.bounds = CGRectMake(0, 0, 10, 40);
    layer.position = CGPointMake(50, self.view.center.y);
    [replicatorLayer addSublayer:layer];
    //
    CABasicAnimation *basicAni = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
    basicAni.toValue = @(0.1);
    basicAni.duration = 0.3;
    basicAni.autoreverses = YES;
    basicAni.repeatCount = NSIntegerMax;
    [layer addAnimation:basicAni forKey:@"layerPosition"];
    
    replicatorLayer.instanceCount = 8;
    CATransform3D transform = CATransform3DIdentity;
    transform = CATransform3DTranslate(transform, 40, 0, 0);
    replicatorLayer.instanceTransform = transform;
    replicatorLayer.instanceDelay = 0.3;
}

运行结果:



NO. 2:催眠等待小圈圈

-(void)lineRoundRoll{
    CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
    replicatorLayer.bounds = self.view.frame;
    replicatorLayer.position = self.view.center;
    [self.view.layer addSublayer:replicatorLayer];
    //
    CALayer *layer = [CALayer layer];
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.cornerRadius = 20;
    layer.bounds = CGRectMake(0, 0, 40, 40);
    layer.position = CGPointMake(50, self.view.center.y);
    [replicatorLayer addSublayer:layer];
    layer.transform = CATransform3DMakeScale(0.01, 0.01, 0.01);
    //
    CABasicAnimation *basicAni = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    basicAni.fromValue = @(1);
    basicAni.toValue = @(0.1);
    basicAni.duration = 0.75;
    basicAni.repeatCount = NSIntegerMax;
    [layer addAnimation:basicAni forKey:@"layerPosition"];
    
    replicatorLayer.instanceCount = 15;
    replicatorLayer.preservesDepth = YES;
    CATransform3D transform = CATransform3DIdentity;
    transform = CATransform3DRotate(transform, M_PI * 2 / 15.0, 0, 0, 1);
    replicatorLayer.instanceTransform = transform;
    replicatorLayer.instanceDelay = 0.05;
    replicatorLayer.instanceAlphaOffset = -1.0 / 15.0;
    //replicatorLayer.instanceBlueOffset = 1.0 / 15;
    //replicatorLayer.instanceColor = [UIColor redColor].CGColor;
}

运行结果:



NO.3:路径跟随

-(void)followPathLayer{
    UIBezierPath *path = [self followPath];
    //
    CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
    replicatorLayer.bounds = self.view.frame;
    replicatorLayer.position = self.view.center;
    [self.view.layer addSublayer:replicatorLayer];
    //
    CALayer *layer = [CALayer layer];
    layer.backgroundColor = [UIColor redColor].CGColor;
    layer.cornerRadius = 5;
    layer.bounds = CGRectMake(0, 0, 10, 10);
    layer.position = CGPointMake(20, self.view.center.y);
    [replicatorLayer addSublayer:layer];
    //
    CAKeyframeAnimation *basicAni = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    basicAni.path = path.CGPath;
    basicAni.duration = 3;
    basicAni.repeatCount = NSIntegerMax;
    [layer addAnimation:basicAni forKey:@"layerPosition"];
    //
    replicatorLayer.instanceCount = 15;
    replicatorLayer.instanceDelay = 0.3;
}

-(UIBezierPath*)followPath{
    //CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(20, self.view.center.y)];
    [path addCurveToPoint:CGPointMake(self.view.bounds.size.width - 20, self.view.center.y) controlPoint1:CGPointMake(130, self.view.center.y - 100) controlPoint2:CGPointMake(240, self.view.center.y + 100)];
    [path closePath];
    //shapeLayer.path = path.CGPath;
    //shapeLayer.lineWidth = 5;
    //shapeLayer.strokeColor = [UIColor grayColor].CGColor;
    //shapeLayer.fillColor = [UIColor clearColor].CGColor;
    //[self.view.layer addSublayer:shapeLayer];
    return path;
}

运行结果:



这几个效果只是提供几个思路,抛砖引玉啦。(这鬼录屏卡帧加模糊,大家将就着看。)


CAScrollLayer

一看到这个你一定想到了UIScrollView,其实它们并没有什么卵关系,并且我个人觉得这个东西好像没有太大的用处。首先,他没有提供有关边界的相关思路,另外,也不能响应交互。只有一下滚到这,滚到那的方法。
同样我们可以看到在这个文件下,还有个CALayerCALayerScrolling的分类,不要以为它给CALayer添加了可滑动的方法,其实只是查找第一个可用的CAScrollLayer,并将制定点或者指定区域滚动到可视范围。
不过为了看一下它的效果,使它响应时间,我们可以用UIView的子类来自己写一个简单的ScrollView:

//
//  YSScrollView.m
//  CAScrollLayerDemo
//
//  Created by ys on 2017/3/13.
//  Copyright © 2017年 ys. All rights reserved.
//

#import "YSScrollView.h"

@implementation YSScrollView
+ (Class)layerClass
{
    return [CAScrollLayer class];
}

- (void)setUp
{
    self.layer.masksToBounds = YES;
    //
    UIPanGestureRecognizer *panGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
    [self addGestureRecognizer:panGes];
}

- (id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame])) {
        [self setUp];
    }
    return self;
}

- (void)panAction:(UIPanGestureRecognizer *)pan
{
    CGPoint offset = self.bounds.origin;
    offset.x -= [pan translationInView:self].x;
    offset.y -= [pan translationInView:self].y;
    //
    [(CAScrollLayer *)self.layer scrollToPoint:offset];
    //
    [pan setTranslation:CGPointZero inView:self];
}

@end

然后调用加载一张大图:
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    YSScrollView *ysSView = [[YSScrollView alloc] initWithFrame:self.view.bounds];
    UIImageView* imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 700, 1040)];
    imageView.image = [UIImage imageNamed:@"0101010.jpg"];
    [self.view addSubview:ysSView];
    [ysSView addSubview:imageView];
}

运行结果:



我们发现,其实他并没有滑动区域的限制,本人才疏学浅,望高人指点什么时候用这个东西。


CATiledLayer

一个大神必备的Layer子类,为节省内存渲染开销提供了途径。比如我们要去加载一个世界地图,精确到你们村的那种,如果全部一次性加载到内存中,这无疑是吃不消的,所以我们可以把地图一片片切开,然后按部分加载,大家联想一下地图应用,应该就知道大致是什么效果。我们直接上代码:

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic, strong) UIScrollView *scrollView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //
    CATiledLayer *tileLayer = [CATiledLayer layer];
    tileLayer.frame = CGRectMake(0, 0, self.view.frame.size.width * 4, self.view.frame.size.height * 4);
    tileLayer.tileSize = self.view.frame.size;
    tileLayer.delegate = self;
    //
    self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:_scrollView];
    self.scrollView.contentSize = tileLayer.frame.size;
    [self.scrollView.layer addSublayer:tileLayer];
    //
    [tileLayer setNeedsDisplay];
}

-(void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)ctx{
    CGRect bounds = CGContextGetClipBoundingBox(ctx);
    NSInteger x = floor(bounds.origin.x / layer.tileSize.width);
    NSInteger y = floor(bounds.origin.y / layer.tileSize.height);
    //
    NSString *imageName = [NSString stringWithFormat: @"image_%@_%@", @(x), @(y)];
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"jpg"];
    UIImage *tileImage = [UIImage imageWithContentsOfFile:imagePath];
    //
    UIGraphicsPushContext(ctx);
    [tileImage drawInRect:bounds];
    UIGraphicsPopContext();
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

运行结果:


其实新加载的图像碎片都是淡入到界面的(万恶的录屏软件,根本看不出来)。这是系统自己带的默认效果,你可以通过调节fadeDuration属性来修改改淡入动画的时长。


CATextLayer

我们还是从系统提供的API入手:

@property(nullable, copy) id string; //显示内容
@property(nullable) CFTypeRef font; //字体
@property CGFloat fontSize; //字号
@property(nullable) CGColorRef foregroundColor; //文字颜色
@property(getter=isWrapped) BOOL wrapped;//是否自适应layer的bounds的大小
@property(copy) NSString *truncationMode;//文字省略方式,其实就是显示不下时省略号的位置
@property(copy) NSString *alignmentMode;// 对齐方式

我们来用它显示一段文字,你可以自由修改一下它的属性来熟悉每个属性的作用:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //
    CATextLayer *textLayer = [CATextLayer layer];
    textLayer.bounds = CGRectMake(0, 0, 200, 200);
    textLayer.position = self.view.center;
    [self.view.layer addSublayer:textLayer];
    
    textLayer.foregroundColor = [UIColor blackColor].CGColor;
    textLayer.alignmentMode = kCAAlignmentLeft;
    textLayer.wrapped = YES;
    //以Retina方式来渲染,防止画出来的文本模糊
    textLayer.contentsScale = [UIScreen mainScreen].scale;
    textLayer.truncationMode = kCATruncationEnd;
    
    UIFont *font = [UIFont systemFontOfSize:15];
    CFStringRef fontName = (__bridge CFStringRef)font.fontName;
    CGFontRef fontRef = CGFontCreateWithFontName(fontName);
    textLayer.font = fontRef;
    textLayer.fontSize = font.pointSize;
    CGFontRelease(fontRef);
    
    NSString *text = @"Age has reached the end of the beginning of a word. May be guilty in his seems to passing a lot of different life became the appearance of the same day; May be back in the past, to oneself the paranoid weird belief disillusionment, these days, my mind has been very messy, in my mind constantly. Always feel oneself should go to do something, or write something. Twenty years of life trajectory deeply shallow, suddenly feel something, do it.";
    
    textLayer.string = text;
}

运行结果:



CAEAGLLayer,AVPlayerLayer

CAEAGLLayer看起来就很高大上,其实真的挺高大上的,没有OpenGL知识基础的很难理解更不用说使用了,哪天,等我学会freeStyle,我唱给你听,呦,呦。(你写代码有freeStyle吗?)

AVPlayerLayer它属于AVFoundation框架,不用怀疑,它就是用来播放视频的,+ (AVPlayerLayer *)playerLayerWithPlayer:(nullable AVPlayer *)player;它的初始化依赖于AVPlayer,当然,它既然是CALayer的子类,我们就可以对它进行酷炫的效果变换,同样也克服了系统提供的播放器由于高度的封装性, 使得自定义播放器变的很难的问题。改天,你有需求,我有时间,不如我们写一个播放器啊。

总结

CALayer的所有子类都说完了,希望在一定的程度上能给你的开发带来方便,仅此而已,我们下期再见。
刚才说到的播放器的需求大概应该必需就是这样的!

上一篇传送门:iOS动画篇_CALayer这些牛逼的子类你造吗

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容