之前講到幾個(gè)常用的
CALayer的子類(lèi),對(duì)對(duì)對(duì),就是他:iOS動(dòng)畫(huà)篇_CALayer這些牛逼的子類(lèi)你造嗎。今天我們來(lái)講其他幾個(gè)吧,要不然,我不說(shuō)你是不是以為我不會(huì)!?。?/p>

那我們今天就從一個(gè)比較酷炫的開(kāi)始:
CATransformLayer
我們先看一下系統(tǒng)有沒(méi)有像之前講過(guò)的幾個(gè)子類(lèi)一樣,給它一些特殊的屬性或者方法:
@interface CATransformLayer : CALayer
@end
啥都沒(méi)有,我擦嘞,但是上面好像有一段描述我們看一下:
/* "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時(shí),對(duì)他的sublayers會(huì)有3D效果,也就是說(shuō)不平面化它的子圖層,大家一提到3D效果,就會(huì)想到一個(gè)神奇的東西景深,先說(shuō)一下景深是個(gè)什么東西,提到景深,那我們就一定要說(shuō)CATransform3D,它定義了一個(gè)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,就是上面提到的景深效果的源頭,我們寫(xiě)一段代碼看一下:
- (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;
}
運(yùn)行結(jié)果:

是不是明顯發(fā)現(xiàn)藍(lán)色的layer3D效果更強(qiáng)烈一些。
下面我們?cè)囈幌逻@樣的代碼:
- (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;
}
運(yùn)行結(jié)果,一片空白,啥都沒(méi)有。
我們做一處改動(dòng):
CATransformLayer *containerLayer = [CATransformLayer layer];
運(yùn)行結(jié)果:

??:所以有人說(shuō)
CATransformLayer便是給他的子圖層添加了景深的效果。瞎搞,把設(shè)置景深的代碼containerTransform.m34 = -1.0 / 500.0;去掉,運(yùn)行,你會(huì)發(fā)現(xiàn)還是一片空白。這就說(shuō)明CATransformLayer并不是這么個(gè)作用。那這個(gè)東西的特殊之處究竟是什么呢?其實(shí)就是上面說(shuō)的:
CATransformLayer并不平面化它的子圖層,所以它能夠用于構(gòu)造一個(gè)層級(jí)分明的3D結(jié)構(gòu)。上代碼:
- (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;
}
運(yùn)行結(jié)果:不出所料,一片空白。
于是,我們把containerLayer由CALayer改成CATransformLayer ,結(jié)果,還是一片空白。
現(xiàn)在,你肯定覺(jué)的我也是在扯淡,下面精彩的部分來(lái)了:
我們給containerLayer添加一個(gè)新的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;
}
運(yùn)行結(jié)果:

現(xiàn)在,我們?cè)侔?code>containerLayer由
CATransformLayer改成CALayer ,結(jié)果,一片空白!你是不是明白了呢?其實(shí)還是上面那句話(huà)!我們利用它來(lái)做一個(gè)立方體:
#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
運(yùn)行結(jié)果:

如果針對(duì)上面的解釋你還不是很理解,那么你可以把這個(gè)立方體的CATransformLayer換成CALayer,試試看嘍。

CAReplicatorLayer
通過(guò)這個(gè)名字,我就確定它和圖層復(fù)制有關(guān),你信不信?
我們看一下系統(tǒng)提供的API:
@interface CAReplicatorLayer : CALayer
@property NSInteger instanceCount; //復(fù)制圖層的個(gè)數(shù),包括加到上面的
@property BOOL preservesDepth; // 子圖層是否平面化(看上面那個(gè)CATransformLayer)
@property CFTimeInterval instanceDelay; // 復(fù)制層動(dòng)畫(huà)延遲時(shí)間
@property CATransform3D instanceTransform; //子圖層的transform變換,一般用來(lái)決定復(fù)制圖層的初始位置以及初始試圖變換
@property(nullable) CGColorRef instanceColor; // 復(fù)制層顏色,該顏色是與本體元素色值相乘,鬼知道是什么顏色
@property float instanceRedOffset; // 復(fù)制層紅色偏移量
@property float instanceGreenOffset; // 復(fù)制層綠色偏移量
@property float instanceBlueOffset; // 復(fù)制層藍(lán)色偏移量
@property float instanceAlphaOffset; // 復(fù)制層透明度偏移量
@end
屬性雖少,變化很大,主要是于核心動(dòng)畫(huà)的強(qiáng)強(qiáng)聯(lián)合,他就有無(wú)限的可能性,三種效果,您上眼:
NO.1:深夜電臺(tái)廣播
-(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;
}
運(yùn)行結(jié)果:

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;
}
運(yùn)行結(jié)果:

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;
}
運(yùn)行結(jié)果:

這幾個(gè)效果只是提供幾個(gè)思路,拋磚引玉啦。(這鬼錄屏卡幀加模糊,大家將就著看。)
CAScrollLayer
一看到這個(gè)你一定想到了UIScrollView,其實(shí)它們并沒(méi)有什么卵關(guān)系,并且我個(gè)人覺(jué)得這個(gè)東西好像沒(méi)有太大的用處。首先,他沒(méi)有提供有關(guān)邊界的相關(guān)思路,另外,也不能響應(yīng)交互。只有一下滾到這,滾到那的方法。
同樣我們可以看到在這個(gè)文件下,還有個(gè)CALayer的CALayerScrolling的分類(lèi),不要以為它給CALayer添加了可滑動(dòng)的方法,其實(shí)只是查找第一個(gè)可用的CAScrollLayer,并將制定點(diǎn)或者指定區(qū)域滾動(dòng)到可視范圍。
不過(guò)為了看一下它的效果,使它響應(yīng)時(shí)間,我們可以用UIView的子類(lèi)來(lái)自己寫(xiě)一個(gè)簡(jiǎn)單的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
然后調(diào)用加載一張大圖:
- (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];
}
運(yùn)行結(jié)果:

我們發(fā)現(xiàn),其實(shí)他并沒(méi)有滑動(dòng)區(qū)域的限制,本人才疏學(xué)淺,望高人指點(diǎn)什么時(shí)候用這個(gè)東西。

CATiledLayer
一個(gè)大神必備的Layer子類(lèi),為節(jié)省內(nèi)存渲染開(kāi)銷(xiāo)提供了途徑。比如我們要去加載一個(gè)世界地圖,精確到你們村的那種,如果全部一次性加載到內(nèi)存中,這無(wú)疑是吃不消的,所以我們可以把地圖一片片切開(kāi),然后按部分加載,大家聯(lián)想一下地圖應(yīng)用,應(yīng)該就知道大致是什么效果。我們直接上代碼:
#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
運(yùn)行結(jié)果:

其實(shí)新加載的圖像碎片都是淡入到界面的(萬(wàn)惡的錄屏軟件,根本看不出來(lái))。這是系統(tǒng)自己帶的默認(rèn)效果,你可以通過(guò)調(diào)節(jié)
fadeDuration屬性來(lái)修改改淡入動(dòng)畫(huà)的時(shí)長(zhǎng)。
CATextLayer
我們還是從系統(tǒng)提供的API入手:
@property(nullable, copy) id string; //顯示內(nèi)容
@property(nullable) CFTypeRef font; //字體
@property CGFloat fontSize; //字號(hào)
@property(nullable) CGColorRef foregroundColor; //文字顏色
@property(getter=isWrapped) BOOL wrapped;//是否自適應(yīng)layer的bounds的大小
@property(copy) NSString *truncationMode;//文字省略方式,其實(shí)就是顯示不下時(shí)省略號(hào)的位置
@property(copy) NSString *alignmentMode;// 對(duì)齊方式
我們來(lái)用它顯示一段文字,你可以自由修改一下它的屬性來(lái)熟悉每個(gè)屬性的作用:
- (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方式來(lái)渲染,防止畫(huà)出來(lái)的文本模糊
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;
}
運(yùn)行結(jié)果:

CAEAGLLayer,AVPlayerLayer
CAEAGLLayer看起來(lái)就很高大上,其實(shí)真的挺高大上的,沒(méi)有OpenGL知識(shí)基礎(chǔ)的很難理解更不用說(shuō)使用了,哪天,等我學(xué)會(huì)freeStyle,我唱給你聽(tīng),呦,呦。(你寫(xiě)代碼有freeStyle嗎?)

AVPlayerLayer它屬于AVFoundation框架,不用懷疑,它就是用來(lái)播放視頻的,+ (AVPlayerLayer *)playerLayerWithPlayer:(nullable AVPlayer *)player;它的初始化依賴(lài)于AVPlayer,當(dāng)然,它既然是CALayer的子類(lèi),我們就可以對(duì)它進(jìn)行酷炫的效果變換,同樣也克服了系統(tǒng)提供的播放器由于高度的封裝性, 使得自定義播放器變的很難的問(wèn)題。改天,你有需求,我有時(shí)間,不如我們寫(xiě)一個(gè)播放器啊。

總結(jié)
CALayer的所有子類(lèi)都說(shuō)完了,希望在一定的程度上能給你的開(kāi)發(fā)帶來(lái)方便,僅此而已,我們下期再見(jiàn)。
剛才說(shuō)到的播放器的需求大概應(yīng)該必需就是這樣的!
