Core Animation总结(二)专用图层

Core Animation总结(一)图层变换(平面 立体)

Core Animation总结(二)专用图层

Core Animation总结(三)动画

Core Animation总结(四)

Core Animation总结(五)性能

Core Animation总结(六)知识点整理

#Core Animation

###CAShapeLayer CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类。你指定诸如颜色和线宽等属性,用CGPath来定义想要绘制的图形,最后CAShapeLayer就自动渲染出来了

  • 渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。
  • 高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。
  • 不会被图层边界剪裁掉。一个CAShapeLayer可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer一样被剪裁掉
  • 不会出现像素化。当你给CAShapeLayer做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。

CAShapeLayer可以用来绘制所有能够通过CGPath来表示的形状。这个形状不一定要闭合,图层路径也不一定要不可破,事实上你可以在一个图层上绘制好几个不同的形状。你可以控制一些属性比如lineWith(线宽,用点表示单位),lineCap(线条结尾的样子),和lineJoin(线条之间的结合点的样子);但是在图层层面你只有一次机会设置这些属性。如果你想用不同颜色或风格来绘制多个形状,就不得不为每个形状准备一个图层了。

// 用CAShapeLayer绘制一个火柴人
// 用UIBezierPath创建图层路径
let path: UIBezierPath = UIBezierPath()
// 画圆
path.move(to: CGPoint(x: 175, y: 100))
path.addArc(withCenter: CGPoint(x: 150, y: 100), radius: 25, startAngle: 0, endAngle: CGFloat.pi*2, clockwise: true)
// 竖线 身子
path.move(to: CGPoint(x: 150, y: 125))
path.addLine(to: CGPoint(x: 150, y: 175))
// 斜线 腿
path.addLine(to: CGPoint(x: 125, y: 225))
// 斜线 腿
path.move(to: CGPoint(x: 150, y: 175))
path.addLine(to: CGPoint(x: 175, y: 225))
path.move(to: CGPoint(x: 100, y: 150))
path.addLine(to: CGPoint(x: 200, y: 150))

let shapeLayer:CAShapeLayer = CAShapeLayer()
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 5
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineCap = kCALineCapRound
shapeLayer.path = path.cgPath
self.view.layer.addSublayer(shapeLayer)
// 有2个圆角一个直角的矩形
let rect: CGRect = CGRect(x: 100, y: 100, width: 150, height: 100)
let size: CGSize = CGSize(width: 20, height: 20)
// 右上 右下 圆角
let corners: UIRectCorner = [UIRectCorner.topRight,UIRectCorner.bottomRight]
let path: UIBezierPath = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: size)

let shapeLayer:CAShapeLayer = CAShapeLayer()
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 5
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineCap = kCALineCapRound
shapeLayer.path = path.cgPath
self.view.layer.addSublayer(shapeLayer)

###CATextLayer Core Animation提供了一个CALayer的子类CATextLayer,它以图层的形式包含了UILabel几乎所有的绘制特性,并且额外提供了一些新的特性。

CATextLayer使用了Core text,并且渲染得非常快。

let v = UIView(frame: CGRect(x: 100, y: 100, width: 150, height: 100))
self.view.addSubview(v)

let textLayer: CATextLayer = CATextLayer()
textLayer.frame = v.bounds
v.layer.addSublayer(textLayer)

textLayer.foregroundColor = UIColor.black.cgColor
textLayer.alignmentMode = kCAAlignmentJustified
textLayer.isWrapped = true
/*
 contentScale属性,用来决定图层内容应该以怎样的分辨率来渲染。
 contentsScale并不关心屏幕的拉伸因素而总是默认为1.0。
 如果我们想以Retina的质量来显示文字,我们就得手动地设置CATextLayer的contentsScale属性
 */
textLayer.contentsScale = UIScreen.main.scale
// 纯文本
let txt = "用NSAttributedString实现一个富文本标签。"
// 富文本
let att: NSMutableAttributedString = NSMutableAttributedString(string: txt)
textLayer.string = txt
textLayer.string = att

###CATransformLayer

//
//  ViewController.swift
//  Demo
//
//  Created by joker on 2016/11/9.
//  Copyright © 2016年 joker. All rights reserved.
//
import UIKit
import GLKit
class ViewController: UIViewController {
    
    var v: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
    
        v = UIView(frame: CGRect(x: 50, y: 50, width: 200, height: 300))
        v.backgroundColor = UIColor(white: 0.7, alpha: 0.3)
        self.view.addSubview(v)
        
        var pt: CATransform3D = CATransform3DIdentity
        pt.m34 = -1/500
        self.view.layer.sublayerTransform = pt
        
        var c1t: CATransform3D = CATransform3DIdentity
        c1t = CATransform3DTranslate(c1t, -100, 0, 0)
        let cube1:CALayer = cube(transform: c1t)
        v.layer.addSublayer(cube1)
        
        var c2t: CATransform3D = CATransform3DIdentity
        c2t = CATransform3DTranslate(c2t, 100, 0, 0)
        c2t = CATransform3DRotate(c2t, -CGFloat.pi/4, 1, 0, 0)
        c2t = CATransform3DRotate(c2t, -CGFloat.pi/4, 0, 1, 0)
        let cube2: CALayer = cube(transform: c2t)
        v.layer.addSublayer(cube2)
        
    }
    func cube(transform:CATransform3D) -> CALayer {
        let cube: CATransformLayer = CATransformLayer()
        //1
        var ct:CATransform3D = CATransform3DMakeTranslation(0, 0, 50)
        cube.addSublayer(self.face(transform: ct))
        //2
        ct = CATransform3DMakeTranslation(50, 0, 0)
        ct = CATransform3DRotate(ct, CGFloat.pi/2, 0, 1, 0)
        cube.addSublayer(self.face(transform: ct))
        //3
        ct = CATransform3DMakeTranslation(0, -50, 0)
        ct = CATransform3DRotate(ct, CGFloat.pi/2, 1, 0, 0)
        cube.addSublayer(self.face(transform: ct))
        //4
        ct = CATransform3DMakeTranslation(0, 50, 0)
        ct = CATransform3DRotate(ct, -CGFloat.pi/2, 1, 0, 0)
        cube.addSublayer(self.face(transform: ct))
        //5
        ct = CATransform3DMakeTranslation(-50, 0, 0)
        ct = CATransform3DRotate(ct, -CGFloat.pi/2, 0, 1, 0)
        cube.addSublayer(self.face(transform: ct))
        //6
        ct = CATransform3DMakeTranslation(0, 0, -50)
        ct = CATransform3DRotate(ct, CGFloat.pi, 0, 1, 0)
        cube.addSublayer(self.face(transform: ct))
        
        let vSize: CGSize = v.bounds.size
        cube.position = CGPoint(x: vSize.width/2, y: vSize.height/2)
        cube.transform = transform
        return cube
    }
    func face(transform:CATransform3D) -> CALayer{
        let face:CALayer = CALayer()
        face.frame = CGRect(x: -50, y: -50, width: 100, height: 100)
        face.transform = transform
        // 随机颜色
        let red: CGFloat = CGFloat(arc4random_uniform(255))/CGFloat(255.0)
        let green: CGFloat = CGFloat( arc4random_uniform(255))/CGFloat(255.0)
        let blue: CGFloat = CGFloat(arc4random_uniform(255))/CGFloat(255.0)
        let color: UIColor = UIColor(red: red, green: green, blue: blue, alpha: 0.3)
        // 背景色
        face.backgroundColor = color.cgColor
        return face
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

###CAGradientLayer CAGradientLayer是用来生成两种或更多颜色平滑渐变的,使用了硬件加速。

//CAGradientLayer是用来生成两种或更多颜色平滑渐变的
let gradientLayer:CAGradientLayer = CAGradientLayer()
gradientLayer.frame = CGRect(x: 100, y: 100, width: 150, height: 100)
self.view.layer.addSublayer(gradientLayer)
/*
 colors属性可以包含很多颜色,所以创建一个彩虹一样的多重渐变也是很简单的。
 默认情况下,这些颜色在空间上均匀地被渲染
 红色 绿色 蓝色 渐变
 */
gradientLayer.colors = [UIColor.red.cgColor, UIColor.green.cgColor, UIColor.blue.cgColor]
/*
 locations属性是一个浮点数值的数组
 这些浮点数定义了colors属性中每个不同颜色的位置,
 0.0代表着渐变的开始,1.0代表着结束。
 */
gradientLayer.locations = [0.0, 0.3, 0.5]
/*
 startPoint和endPoint属性,他们决定了渐变的方向
 左上角坐标是{0, 0},右下角坐标是{1, 1}
 */
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 1)

###CAReplicatorLayer CAReplicatorLayer的目的是为了高效生成许多相似的图层 变换是逐步增加的,每个实例都是相对于前一实例布局 用CAReplicatorLayer生成十个图层组成一个圆圈。

let replicatorLayer: CAReplicatorLayer = CAReplicatorLayer()
replicatorLayer.frame = CGRect(x: 50, y: 50, width: 200, height: 150)
self.view.layer.addSublayer(replicatorLayer)

var transform: CATransform3D = CATransform3DIdentity
transform = CATransform3DTranslate(transform, 0, 100, 0)
transform = CATransform3DRotate(transform, CGFloat.pi/5, 0, 0, 1)
transform = CATransform3DTranslate(transform, 0, -100, 0)
// instanceTransform指定了一个CATransform3D3D变换
replicatorLayer.instanceTransform = transform
// instanceCount属性指定了图层需要重复多少次。
replicatorLayer.instanceCount = 10
/*
 用instanceBlueOffset和instanceGreenOffset属性 通过逐步减少蓝色和绿色通道
 图层在重复的时候,颜色变化
 */
replicatorLayer.instanceBlueOffset = -0.1
replicatorLayer.instanceGreenOffset = -0.1
// 透明递减
replicatorLayer.instanceAlphaOffset = -0.1

let layer: CALayer = CALayer()
layer.frame = CGRect(x: 50, y: 50, width: 50, height: 50)
layer.backgroundColor = UIColor.gray.cgColor
replicatorLayer.addSublayer(layer)

###CAScrollLayer CAScrollLayer是CALayer的子类,用于显示层的一部分。CAScrollLayer的可滚动区域的范围是由它的子层布局来确定的。 CAScrollLayer不提供键盘或鼠标事件处理,也没有提供可见滚动条。

属性 scrollMode 允许滚动方向,可选以下值:

NSString * const kCAScrollNone;         // 禁止滚动
NSString * const kCAScrollVertically;   // 只允许垂直滚动
NSString * const kCAScrollHorizontally; // 只允许水平滚动
NSString * const kCAScrollBoth;         // 可以随便滚动,默认

visibleRect 返回可见区域范围。 此属性是在CALayer的分类中实现的,所以所有CALayer子类都可以调用次方法来获取当前显示的可见区域范围。但是必须要是在CAScrollLayer的子图层。

方法 (void)scrollToPoint:(CGPoint)p 把指定点p滚动到左上角。点坐标可以是负值。

(void)scrollToRect:(CGRect)r 滚动使指定区域r可见。 如果r.size > self.bounds.size,则r.size = self.bounds.size。

(void)scrollPoint:(CGPoint)p 此方法是在CALayer的分类中实现。改方法是从自身开始往父图层找到最近的CAScrollLayer层,然后调用-scrollToPoint: 方法,如果没有找到CAScrollLayer层则不做任何处理。

(void)scrollRectToVisible:(CGRect)r 此方法是在CALayer的分类中实现。改方法是从自身开始往父图层找到最近的CAScrollLayer层,然后调用-scrollToRect: 方法,如果没有找到CAScrollLayer层则不做任何处理。

###CATiledLayer CATiledLayer为载入大图造成的性能问题提供了一个解决方案:将大图分解成小片然后将他们单独按需载入

256*256是CATiledLayer的默认小图大小,默认大小可以通过tileSize属性更改

CATiledLayer需要载入新的小图时,就会调用 drawLayer:inContext: 这个方法 比如用于地图显示

###CAEmitterLayer CAEmitterLayer是一个高性能的粒子引擎,被用来创建实时例子动画如:烟雾,火,雨等等这些效果。

CAEmitterLayer看上去像是许多CAEmitterCell的容器,这些CAEmitierCell定义了一个例子效果。你将会为不同的例子效果定义一个或多个CAEmitterCell作为模版,同时CAEmitterLayer负责基于这些模版实例化一个粒子流。一个CAEmitterCell类似于一个CALayer:它有一个contents属性可以定义为一个CGImage,另外还有一些可设置属性控制着表现和行为。

CAEmitterLayer的属性它自己控制着整个例子系统的位置和形状。一些属性比如birthRate,lifetime和celocity,这些属性在CAEmitterCell中也有。这些属性会以相乘的方式作用在一起

//在一圆中发射不同速度和透明度的粒子创建一个火爆炸的效果
let v = UIView(frame: CGRect(x: 50, y: 50, width: 200, height: 200))
self.view.addSubview(v)
// CAEmitterLayer是一个高性能的粒子引擎,被用来创建实时例子动画如:烟雾,火,雨等等这些效果
let emitterLayer: CAEmitterLayer = CAEmitterLayer()
emitterLayer.frame = v.bounds
v.layer.addSublayer(emitterLayer)
/*
 renderMode,控制着在视觉上粒子图片是如何混合的。
 kCAEmitterLayerAdditive 合并例子重叠部分的亮度使得看上去更亮
 */
emitterLayer.renderMode = kCAEmitterLayerAdditive
emitterLayer.emitterPosition = CGPoint(x: emitterLayer.frame.size.width/2, y: emitterLayer.frame.size.height/2)
//是否将3D例子系统平面化到一个图层(默认值)或者可以在3D空间中混合其他的图层
emitterLayer.preservesDepth = true

//CAEmitterLayer看上去像是许多CAEmitterCell的容器,这些CAEmitierCell定义了一个例子效果
let cell: CAEmitterCell = CAEmitterCell()
cell.contents = UIImage(named: "bg.jpg")?.cgImage
cell.birthRate = 150
cell.lifetime = 5.0
//一个可以混合图片内容颜色的混合色
cell.color = UIColor.red.cgColor
/*
 将alphaSpeed设置为-0.4,
 透明度每过一秒就是减少0.4,
 这样就有发射出去之后逐渐小时的效果。
 */
cell.alphaSpeed = -0.4
cell.velocity = 50
cell.velocityRange = 50
/*
 emissionRange属性的值是2π,从360度任意位置反射出来。
 如果指定一个小一些的值,就可以创造出一个圆锥形
*/
cell.emissionRange = CGFloat.pi*2

emitterLayer.emitterCells = [cell]

###CAEAGLLayer OpenGL提供了Core Animation的基础,它是底层的C接口,直接和iPhone,iPad的硬件通信,极少地抽象出来的方法。OpenGL没有对象或是图层的继承概念。它只是简单地处理三角形。OpenGL中所有东西都是3D空间中有颜色和纹理的三角形。

CAEAGLLayer用来显示任意的OpenGL图形。

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *glView;
@property (nonatomic, strong) EAGLContext *glContext;
@property (nonatomic, strong) CAEAGLLayer *glLayer;
@property (nonatomic, assign) GLuint framebuffer;
@property (nonatomic, assign) GLuint colorRenderbuffer;
@property (nonatomic, assign) GLint framebufferWidth;
@property (nonatomic, assign) GLint framebufferHeight;
@property (nonatomic, strong) GLKBaseEffect *effect;

@end

@implementation ViewController

- (void)setUpBuffers
{
    //set up frame buffer
    glGenFramebuffers(1, &_framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);

    //set up color render buffer
    glGenRenderbuffers(1, &_colorRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderbuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderbuffer);
    [self.glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.glLayer];
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_framebufferWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_framebufferHeight);

    //check success
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        NSLog(@"Failed to make complete framebuffer object: %i", glCheckFramebufferStatus(GL_FRAMEBUFFER));
    }
}
- (void)tearDownBuffers
{
    if (_framebuffer) {
        //delete framebuffer
        glDeleteFramebuffers(1, &_framebuffer);
        _framebuffer = 0;
    }

    if (_colorRenderbuffer) {
        //delete color render buffer
        glDeleteRenderbuffers(1, &_colorRenderbuffer);
        _colorRenderbuffer = 0;
    }
}
- (void)drawFrame {
    //bind framebuffer & set viewport
    glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
    glViewport(0, 0, _framebufferWidth, _framebufferHeight);

    //bind shader program
    [self.effect prepareToDraw];

    //clear the screen
    glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.0, 0.0, 0.0, 1.0);

    //set up vertices
    GLfloat vertices[] = {
        -0.5f, -0.5f, -1.0f, 0.0f, 0.5f, -1.0f, 0.5f, -0.5f, -1.0f,
    };

    //set up colors
    GLfloat colors[] = {
        0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
    };

    //draw triangle
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(GLKVertexAttribColor,4, GL_FLOAT, GL_FALSE, 0, colors);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    //present render buffer
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderbuffer);
    [self.glContext presentRenderbuffer:GL_RENDERBUFFER];
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    //set up context
    self.glContext = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
    [EAGLContext setCurrentContext:self.glContext];

    //set up layer
    self.glLayer = [CAEAGLLayer layer];
    self.glLayer.frame = self.glView.bounds;
    [self.glView.layer addSublayer:self.glLayer];
    self.glLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking:@NO, kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8};

    //set up base effect
    self.effect = [[GLKBaseEffect alloc] init];

    //set up buffers
    [self setUpBuffers];

    //draw frame
    [self drawFrame];
}
- (void)viewDidUnload
{
    [self tearDownBuffers];
    [super viewDidUnload];
}
- (void)dealloc
{
    [self tearDownBuffers];
    [EAGLContext setCurrentContext:nil];
}
@end

###AVPlayerLayer AVPlayerLayer不是Core Animation框架的一部分(AV前缀看上去像),AVPlayerLayer是有别的框架(AVFoundation)提供的,它和Core Animation紧密地结合在一起,提供了一个CALayer子类来显示自定义的内容类型。


参考资料:https://zsisme.gitbooks.io/ios-/content/index.html

转载于:https://my.oschina.net/asjoker/blog/786446

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值