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閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容