iOS Core Animation Advanced Techniques-专用图层

上五章节:

  1. 图层树
  2. 图层的寄宿图
  3. 图层几何学
  4. 图层视觉效果
  5. 图层变换

这篇随笔主要介绍有关专用图层。

专用图层都属于CALayer的子类:

  • CAShapeLayer:
    • 通过CGPath表示的任何矢量图形而不是bitmap来绘制图层子类,类似用Core Graphics向CALayer的内容绘制一个路径渲染出图形,但是使用CAShapeLayer有以下优点:

1.渲染快速,因为使用了硬件加速

2.高效使用内存,因为不需要像普通CALayer一样创建一个寄宿图形

3.不会被图层边界裁剪,不像使用Core Graphics在普通CALayer中绘图会被边界裁剪内容

4.不会出现像素化,给CAShapeLayer做3D变换时不像一个有寄宿图的普通CALayer一样变得像素化

    • 通过CGPath绘制的形状不一定要闭合,可以在一个图层绘制好几个不同的形状,
    • 通过控制属性如
    1. lineWith:线宽
    2. lineCap:线条结尾的样子
    3. lineJoin:线条之间的结合点的样子
    • 使用例子:
      • //这里使用的是UIBezierPath绘制的路径,不用考虑人工释放CGPath
      • UIBezierPath *path=[[UIBezierPath alloc]init];
      • [path moveToPoint:CGPointMake(175,100)];
      • [path addArcWithCenter:CGPointMake(150,100)radius:25 startAngle:0 endAngle:2*M_PI clockwise:YES];
      • [path moveToPoint:CGPointMake(150, 125)];
      • [path addLineToPoint:CGPointMake(150, 175)];
      • [path addLineToPoint:CGPointMake(125, 225)];
      • [path moveToPoint:CGPointMake(150, 175)];
      • [path addLineToPoint:CGPointMake(175, 225)];
      • [path moveToPoint:CGPointMake(100, 150)];
      • [path addLineToPoint:CGPointMake(200, 150)];
      • CAShapeLayer *shapeLayer=[CAShapeLayer layer];
      • shapeLayer.strokeColor=[UIColor redColor].CGColor;
      • shapeLayer.fillColor=[UIColor clearColor].CGColor;
      • shapeLayer.lineWidth=5;
      • shapeLayer.lineJoin=kCALineJoinRound;
      • shapeLayer.lineCap=kCALineCapRound;
      • shapeLayer.path=path.CGPath;
      • [myView.layer addSublayer:shapeLayer];
    • 该专用图层还有一个特色就是可以单独指定每一个角的曲率,先用UIBezierPath创建一个指定特定角圆角的路径
    • 使用例子:
      • CGRect rect=CGRectMake(50,50,100,100);
      • CGSize radii=CGSizeMake(20,20);
      • UIRectCorner corners=UIRectCornerTopRight|UIRectCornerBottomRight|UIRectCornerBottomLeft;
      • UIBezierPath *path=[UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners cornerRadii:radii];
      • CAShapeLayer *shapeLayer=[CAShapeLayer layer];
      • shapeLayer.strokeColor=[UIColor redColor].CGColor;
      • shapeLayer.fillColor=[UIColor clearColor].CGColor;
      • shapeLayer.lineWidth=5;
      • shapeLayer.lineJoin=kCALineJoinRound;
      • shapeLayer.lineCap=kCALineCapRound;
      • shapeLayer.path=path.CGPath;
      • [myView.layer addSublayer:shapeLayer];
  • CATextLayer:
    • 以图层的形式包含了UILabel几乎所有的绘制特性,还额外提供了一些新的特性,切比UILabel渲染快
    • 使用例子:
      • //用CATextLayer来显示一些文字
      • CATextLayer *textLayer=[CATextLayer layer];
      • textLayer.frame=myView.bounds;
      • [myView.layer addSublayer:textLayer];
      • textLayer.foregroundColor=[UIColor blackColor].CGColor;
      • textLayer.alignmentMode=kCAAlignmentJustified;
      • textLayer.wrapped=YES;
      • 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 = @"Lorem ipsum dolor sit amet, consectetur adipiscing \ elit. Quisque massa arcu, eleifend vel varius in, facilisis pulvinar \ leo. Nunc quis nunc at mauris pharetra condimentum ut ac neque. Nunc elementum, libero ut porttitor dictum, diam odio congue lacus, vel \ fringilla sapien diam at purus. Etiam suscipit pretium nunc sit amet \ lobortis";
      • textLayer.string=text;
      • textLayer.contentsScale=[UIScreen mainScreen].scale;
  • CATransformLayer:
    • 不同于普通的CALayer,因为不能显示自己的内容,只有当存在了一个能作用于子图层的变换才真正存在
    • 不平面化它的子图层
    • 使用例子:
      • -(CALayer *)faceWithTransform:(CATransform3D)transform{
      • CALayer *face=[CALayer layer];
      • face.frame=CGRectMake(-50,-50,100,100);
      • CGFloat red = (rand() / (double)INT_MAX);
      • CGFloat green = (rand() / (double)INT_MAX);
      • CGFloat blue = (rand() / (double)INT_MAX);
      • face.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].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]];//把正常CALayer往CATransformLayer添加让它拥有子图层
      • ct = CATransform3DMakeTranslation(50, 0, 0);
      • ct = CATransform3DRotate(ct, M_PI_2, 0, 1, 0);
      • [cube addSublayer:[self faceWithTransform:ct]];
      • ct = CATransform3DMakeTranslation(0, -50, 0);
      • ct = CATransform3DRotate(ct, M_PI_2, 1, 0, 0);
      • [cube addSublayer:[self faceWithTransform:ct]];
      • ct = CATransform3DMakeTranslation(0, 50, 0);
      • ct = CATransform3DRotate(ct, -M_PI_2, 1, 0, 0);
      • [cube addSublayer:[self faceWithTransform:ct]];
      • ct = CATransform3DMakeTranslation(-50, 0, 0);
      • ct = CATransform3DRotate(ct, -M_PI_2, 0, 1, 0);
      • [cube addSublayer:[self faceWithTransform:ct]];
      • ct = CATransform3DMakeTranslation(0, 0, -50);
      • ct = CATransform3DRotate(ct, M_PI, 0, 1, 0);
      • [cube addSublayer:[self faceWithTransform:ct]];
      • CGSize containerSize=self.containerView.bounds.size;
      • cube.position=CGPointMake(containerSize.width / 2.0, containerSize.height / 2.0);
      • cube.transform=transform;
      • return cube;
      • }
      • -(void)viewDidLoad{
      • [super viewDidLoad];
      • CATransform3D pt=CATransform3DIdentity;
      • pt.m34=-1.0/500.0;
      • containerView.layer.sublayerTransform=pt;
      • CATransform3D c1t = CATransform3DIdentity;
      • c1t = CATransform3DTranslate(c1t, -100, 0, 0);
      • CALayer *cube1 = [self cubeWithTransform:c1t];
      • [containerView.layer addSublayer:cube1];
      • CATransform3D c2t = CATransform3DIdentity;
      • c2t = CATransform3DTranslate(c2t, 100, 0, 0);
      • c2t = CATransform3DRotate(c2t, -M_PI_4, 1, 0, 0);
      • c2t = CATransform3DRotate(c2t, -M_PI_4, 0, 1, 0);
      • CALayer *cube2 = [self cubeWithTransform:c2t];
      • [containerView.layer addSublayer:cube2];
      • }
  • CAGradientLayer:
    • 用来生成两种或更多颜色平滑渐变
    • 该专用图层使用了硬件加速
    • 使用步骤:

1.把切换颜色CGColorRef放到一个数组中

2.把数组赋值给该专用图层的colors属性

3.设置startPoint和sendPoint属性,决定渐变方向,以单位坐标系进行定义,左上角{0,0},右下角{1,1}

    • 使用例子:
      • CAGradientLayer *gradientLayer = [CAGradientLayer layer];
      • gradientLayer.frame = containerView.bounds;
      • [containerView.layer addSublayer:gradientLayer];
      • gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor, (__bridge id)[UIColor blueColor].CGColor];
      • gradientLayer.startPoint = CGPointMake(0, 0);
      • gradientLayer.endPoint = CGPointMake(1, 1);
    • 默认颜色在空间上均匀渲染,可以通过locations属性,一个浮点值数组,元素为NSNumber,调整颜色空间
    • 0.0表示渐变开始,1.0代表结束,需要确保locations数组大小与colors数组大小相同,不然得到空白的渐变
    • 使用例子:
      • CAGradientLayer *gradientLayer = [CAGradientLayer layer];
      • gradientLayer.frame = containerView.bounds;
      • [containerView.layer addSublayer:gradientLayer];
      • gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor, (__bridge id) [UIColor yellowColor].CGColor, (__bridge id)[UIColor greenColor].CGColor];
      • gradientLayer.locations = @[@0.0, @0.25, @0.5];
      • gradientLayer.startPoint = CGPointMake(0, 0);
      • gradientLayer.endPoint = CGPointMake(1, 1);
  • CAReplicatorLayer:
    • 可以高效生成许多相似图层
    • instanceCount属性指定图层重复次数
    • instanceTransform属性指定一个CATransform3D 3D变换
    • 变换是逐步增加的,每个实例相对前一个实例布局
    • 使用例子:
      • CAReplicatorLayer *replicator=[CAReplicatorLayer layer];
      • replicator.frame=containerView.bounds;
      • [containerView.layer addSublayer:replicator];
      • replicator.instanceCount=10;
      • CATransform3D transform=CATransform3DIdentity;
      • transform=CATransform3DTranslate(transform,0,200,0);
      • transform = CATransform3DRotate(transform, M_PI / 5.0, 0, 0, 1);
      • transform = CATransform3DTranslate(transform, 0, -200, 0);
      • replicator.instanceTransform = transform;
      • replicator.instanceBlueOffset=-0.1;
      • replicator.instanceGreenOffset=-0.1;//逐步减少蓝色和绿色通道,我们逐渐将图层颜色转换成了红色
      • CALayer *layer = [CALayer layer];
      • layer.frame = CGRectMake(100.0f, 100.0f, 100.0f, 100.0f);
      • layer.backgroundColor = [UIColor whiteColor].CGColor;
      • [replicator addSublayer:layer];
    • 一个拥有自带视图倒影效果基于CAReplicatorLayer实现的UIView子类:
      • #import "ReflectionView.h"
      • #import <QuartzCore/QuartzCore.h>
      • @implementation ReflectionView
      • + (Class)layerClass
      • {
      • return [CAReplicatorLayer class];
      • }
      • - (void)setUp
      • {
      • //configure replicator
      • CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
      • layer.instanceCount = 2;
      • //move reflection instance below original and flip vertically
      • CATransform3D transform = CATransform3DIdentity;
      • CGFloat verticalOffset = self.bounds.size.height + 2;
      • transform = CATransform3DTranslate(transform, 0, verticalOffset, 0);
      • transform = CATransform3DScale(transform, 1, -1, 0);
      • layer.instanceTransform = transform;
      • //reduce alpha of reflection layer
      • layer.instanceAlphaOffset = -0.6;
      • }
      • - (id)initWithFrame:(CGRect)frame
      • {
      • //this is called when view is created in code
      • if ((self = [super initWithFrame:frame])) {
      • [self setUp];
      • }
      • return self;
      • }
      • - (void)awakeFromNib
      • {
      • //this is called when view is created from a nib
      • [self setUp];
      • }
      • @end
  • CAScrollLayer
    • 在一个独立图层中,想显示一个大图层里面的一小部分,希望能随意滑动,便可使用该专用图层
    • -scrollToPoint:方法,自动适应bounds的原点以便图层内容出现在滑动的地方
    • 因图层不负责将触摸事件转换为滑动事件,所以既不渲染滚动条,也不实现如滑动反弹等行为
    • 使用步骤:

1.用CAScrollLayer作为视图的数组图层

2.创建一个自定义UIView,用UIPanGestureRecognizer实现触摸事件响应

    • 使用例子:
      • #import "ScrollView.h"
      • #import <QuartzCore/QuartzCore.h>
      • @implementation ScrollView
      • + (Class)layerClass
      • {
      • return [CAScrollLayer class];
      • }
      • - (void)setUp
      • {
      • //enable clipping
      • self.layer.masksToBounds = YES;
      • //attach pan gesture recognizer
      • UIPanGestureRecognizer *recognizer = nil;
      • recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
      • [self addGestureRecognizer:recognizer];
      • }
      • - (id)initWithFrame:(CGRect)frame
      • {
      • //this is called when view is created in code
      • if ((self = [super initWithFrame:frame])) {
      • [self setUp];
      • }
      • return self;
      • }
      • - (void)awakeFromNib {
      • //this is called when view is created from a nib
      • [self setUp];
      • }
      • - (void)pan:(UIPanGestureRecognizer *)recognizer
      • {
      • //get the offset by subtracting the pan gesture
      • //translation from the current bounds origin
      • CGPoint offset = self.bounds.origin;
      • offset.x -= [recognizer translationInView:self].x;
      • offset.y -= [recognizer translationInView:self].y;
      • //scroll the layer
      • [(CAScrollLayer *)self.layer scrollToPoint:offset];
      • //reset the pan gesture translation
      • [recognizer setTranslation:CGPointZero inView:self];
      • }
      • @end
    • 不同于UIScrollView,定制的互动视图类没有实现任何边界检查

 

  • CATiledLayer:
    • 当需要绘制很大图片时,如果读取整个图片,载入大图会很慢,即时个人能接受载入慢甚至卡主线程,但是
    • 因为所有显示在屏幕上的图片最终会被转换为OpenGL纹理,该纹理有一个最大尺寸(2048*2048或4096*4096)
    • 该专用图层便是解决该类问题而存在:将大图分解成小片然后将他们单独按需载入
    • 使用步骤:

1.使用Mac OS命令行程序,使用CATiledLayer将一个大图裁剪成多个小图并存储到不同文件中

/*裁剪图片成小图的终端程序,*/

      • #import <AppKit/AppKit.h>
      • int main(int argc, const char * argv[])
      • {
      • @autoreleasepool{
      • //handle incorrect arguments
      • if (argc < 2) {
      • NSLog(@"TileCutter arguments: inputfile");
      • return 0;
      • }
      • //input file
      • NSString *inputFile = [NSString stringWithCString:argv[1] encoding:NSUTF8StringEncoding];
      • //tile size
      • CGFloat tileSize = 256; //output path
      • NSString *outputPath = [inputFile stringByDeletingPathExtension];
      • //load image
      • NSImage *image = [[NSImage alloc] initWithContentsOfFile:inputFile];
      • NSSize size = [image size];
      • NSArray *representations = [image representations];
      • if ([representations count]){
      • NSBitmapImageRep *representation = representations[0];
      • size.width = [representation pixelsWide];
      • size.height = [representation pixelsHigh];
      • }
      • NSRect rect = NSMakeRect(0.0, 0.0, size.width, size.height);
      • CGImageRef imageRef = [image CGImageForProposedRect:&rect context:NULL hints:nil];
      • //calculate rows and columns
      • NSInteger rows = ceil(size.height / tileSize);
      • NSInteger cols = ceil(size.width / tileSize);
      • //generate tiles
      • for (int y = 0; y < rows; ++y) {
      • for (int x = 0; x < cols; ++x) {
      • //extract tile image
      • CGRect tileRect = CGRectMake(x*tileSize, y*tileSize, tileSize, tileSize);
      • CGImageRef tileImage = CGImageCreateWithImageInRect(imageRef, tileRect);
      • //convert to jpeg data
      • NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:tileImage];
      • NSData *data = [imageRep representationUsingType: NSJPEGFileType properties:nil];
      • CGImageRelease(tileImage);
      • //save file
      • NSString *path = [outputPath stringByAppendingFormat: @"_%02i_%02i.jpg", x, y];
      • [data writeToFile:path atomically:NO];
      • }
      • }
      • }
      • return 0;
      • }
      • /*
      • 然后在终端调用
      • > path/to/TileCutterApp path/to/Snowman.jpg
      • */

2.使用CATiledLayer专用图层结合UIScrollView使用,实现-drawLayer:inContext:方法

      • 当需要载入新小图时,CATiledLayer会调用该方法。
      • 使用例子:
        • CATiledLayer *tileLayer=[CATiledLayer layer];
        • tileLayer.frame=CGRectMake(0,0,2048,2048);
        • tileLayer.delegate=self;
        • tileLayer.contentsScale = [UIScreen mainScreen].scale;
        • [scrollView.layer addSublayer:tileLayer];
        • scrollView.contentSize=tileLayer.frame.size;
        • [tileLayer setNeedsDisplay];
        • -(void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)ctx{
        • CGRect bounds=CGContextGetClipBoundingBox(ctx);
        • NSInteger x=floor(bounds.origin.x/layer.tileSize.width*scale);
        • NSInteger y=floor(bounds.origin.y/layer.tileSize.height*scale);
        • NSString *imageName=[NSString stringWithFormat:@"Snowman_%02i_%02i",x,y];
        • NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"jpg"];
        • UIImage *tileImage = [UIImage imageWithContentsOfFile:imagePath];
        • //draw tile
        • UIGraphicsPushContext(ctx);
        • [tileImage drawInRect:bounds];
        • UIGraphicsPopContext();
        • }
        • /*
        • 滑动时,CATiledLayer载入小图默认带淡入效果进入界面,
        • 可以通过fadeDuration属性改变淡入时长或直接禁用掉;
        • -drawLayer:inContext:方法可以在多个线程中同时地并发调用,需小心线程安全
        • */

 

  • CAEmitterLayer
    • 一个高性能的粒子引擎,用来创建实时例子动画如:烟雾,火,雨等效果
    • 该专用图层像是许多CAEmitterCell(定义一个粒子效果)的容器
    • 一般需要为不同的粒子效果定义一个或多个CAEmitterCell作为模版
    • 一个CAEmitterCell类似一个CALayer:
      • 有一个contents属性可以定义一个CGImage,
      • 另外有一些可设置属性控制表现与行为
      • 基本属性可以分3种:

1.粒子的某一属性的初始值,如color

2.粒子某一属性的变化范围

3.指定值在时间线上的变化

    • 而该专用图层负责基于这些模版实例化一个粒子流,并且通过属性控制整个例子系统的位置与形状
    • 该专用图层的一些属性:
      • birthTate
      • lifetime
      • celocity
    • /*同样在CAEmitterCell中也有上面这三个属性,最终这些属性以相乘方式作用在一起*/
      • preservesDepth:是否将3D粒子系统平面化到一个图层(默认)或者可以在3D空间中混合其它图层
      • renderMode:控制着在视觉上例子图片是如何混合。
    • 使用例子:
      • CAEmitterLayer *emitter = [CAEmitterLayer layer];
      • emitter.frame = self.containerView.bounds;
      • [self.containerView.layer addSublayer:emitter];
      • emitter.renderMode = kCAEmitterLayerAdditive;
      • emitter.emitterPosition = CGPointMake(emitter.frame.size.width / 2.0, emitter.frame.size.height / 2.0);
      • CAEmitterCell *cell = [[CAEmitterCell alloc] init];
      • cell.contents = (__bridge id)[UIImage imageNamed:@"Spark.png"].CGImage;
      • cell.birthRate = 150;
      • cell.lifetime = 5.0;
      • cell.color = [UIColor colorWithRed:1 green:0.5 blue:0.1 alpha:1.0].CGColor;
      • cell.alphaSpeed = -0.4;
      • cell.velocity = 50;
      • cell.velocityRange = 50;
      • cell.emissionRange = M_PI * 2.0;
      • emitter.emitterCells = @[cell];

 

  • CAEAGLLayer
    • OpenGL提供Core Animation的基础,是底层的C接口,没有对象或是图层的继承概念,直接与硬件通信
    • iOS5引入GLKit,去掉了一些设置OpenGL的复杂性,提供一个叫CLKView的UIView子类,处理大部分的设置与绘制工作
    • 但是仍需通过CAEAGLLayer配置各种各样的OpenGL绘图缓冲的底层配置项,CAEAGLLayer用来显示任意OpenGL图形
    • 使用前需要引入GLKit与OpenGLES框架
    • 以下例子,使用OpenGL ES2.0的绘图上下文,并渲染一个有色三角:
      • #import "ViewController.h"
      • #import <QuartzCore/QuartzCore.h>
      • #import <GLKit/GLKit.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是由AVFoundation框架提供
    • 用来播放视频,是MPMoivePlayer的底层实现,提供显示视频的底层控制
    • 通过调用+playerLayerWithPlayer:方法创建一个绑定了视频播放器的图层
    • 或者先创建一个图层,用play属性绑定一个AVPlayer实例
    • 使用例子:
      • #import <AVFoundation/AVFoundation.h>
      • NSURL *URL = [[NSBundle mainBundle] URLForResource:@"Ship" withExtension:@"mp4"];
      • AVPlayer *player = [AVPlayer playerWithURL:URL];
      • AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
      • playerLayer.frame = self.containerView.bounds;
      • [self.containerView.layer addSublayer:playerLayer];
      • [player play];
    • 因为该专用图层是CALayer的子类,也就可以对其进行3D,圆角,有色边框,蒙板,阴影等效果设置
    • 使用例子:(续上使用例子)
      • playerLayer.frame = self.containerView.bounds;
      • [self.containerView.layer addSublayer:playerLayer];
      • CATransform3D transform = CATransform3DIdentity;
      • transform.m34 = -1.0 / 500.0;
      • transform = CATransform3DRotate(transform, M_PI_4, 1, 1, 0);
      • playerLayer.transform = transform;
      • playerLayer.masksToBounds = YES;
      • playerLayer.cornerRadius = 20.0;
      • playerLayer.borderColor = [UIColor redColor].CGColor;
      • playerLayer.borderWidth = 5.0;
      • [player play];
posted @ 2016-03-12 20:59  Jk_Chan  阅读(278)  评论(0编辑  收藏  举报