iOS核心动画(专用图层篇)
之前的文章我们了解了Core Animation中图层的一些基础知识。没有看过的传送门在此:
iOS核心动画基础篇
那么在了解了这些基础知识之后,接下来进入专用图层的了解
苹果为了方便和性能,封装了几种专用图层,各有特性。
CAShapeLayer
那么什么时候用CAShapeLayer呢?
当我们想要一个任意形状的layer。就可以使用CAShapeLayer
虽然你可以用Core Graphics绘制图形,但是使用CAShapeLayer是存在如下优势的:
- 渲染快速。CAShapeLayer使用了硬件加速
- 高效使用内存。CAShapeLayer不需要创建寄宿图形就可以显示
- 不会被图层边界裁剪
- 不会出现像素化。因为它是通过矢量图形绘制的
那么怎么用CAShapeLayer呢?
通过指定一个CGPath来定义想要绘制的图形,CAShapeLayer就可以自动渲染。
通过属性控制lineWith(线宽,用点表示单位),lineCap(线条结尾的样子),和lineJoin(线条之间的结合点的样子);
通过属性控制 fillColor(填充颜色),strokeColor(线条颜色)
通常我们创建UIBezierPath 的类来转化成CGpath做为CAShaperLayer的path,就可以使用ARC了。
举个栗子更容易理解,下面代码生成了一个有三个圆角一个直角的矩形
CGRect rect = CGRectMake(50, 50, 100, 100);
CGSize radii = CGSizeMake(20, 20);
UIRectCorner corners = UIRectCornerTopRight | UIRectCornerBottomRight | UIRectCornerBottomLeft;
//create path
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners cornerRadii:radii];
CAShapeLayer *slayer = [CAShapeLayer layer];
slayer.path = path.CGPath;
slayer.fillColor = [UIColor clearColor].CGColor;
slayer.strokeColor = [UIColor greenColor].CGColor;
CATextLayer
CATextLayer的优点是什么?
以图层的形式包含了UILabel几乎所有的绘制特性,并且额外提供了一些新的特性。
CATextLayer要比UILabel渲染的快的多。因为CATextLayer使用的是Core Text。
如果直接使用CATextLayer实现文字的话,layer的contentScale是默认的1.所以如果要Retina屏幕的显示效果的话,我们就需要下面的代码
textLayer.contentsScale = [UIScreen mainScreen].scale;
那么怎么用CATextLayer呢?
CATextLayer的font和string属性都是id类型。你可以选择任意框架的数据传入。比如CF开头,或者CT开头。string属性,你可以传入的是NSSTtring类型,也可以是NSAttributedString
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";
//set layer text
textLayer.string = text;
我们已经证实了CATextLayer要比UILabel的性能更高。如果我们需要一个UILabel的替代品,最好能像一般的视图一样工作。
接下来我们把
CATextLayer进行封装
我们应该创建一个UILabel的子类,如果只是在这个子类中创建CATextLayer子图层并重写显示文本的方法,但是还是会有drawRect:方法创建的空的寄宿图层。而且子图层因为不支持自动缩放和自动布局,不能自动适应视图的大小。
我们可以通过改写UIView的+layerClass方法返回自己想要的图层类型。UIView会在初始化的时候调用+layerClass方法来创建宿主图层。就像这样
+ (Class)layerClass
{
return [CATextLayer class];
}
- (CATextLayer *)textLayer
{
return (CATextLayer *)self.layer;
}
CAReplicatorLayer
接下来说一个很有意思的Layer
CAReplicatorLayer 是为了高效生成许多相似的图层,他会复制一个或多个图层的子视图,并在每个子视图上应用不同的变换。
这个Layer用起来也不难
instanceCount 指定图层需要复制多少次。
instanceTransform 指定一个3D变换。变换是逐步增加的。每个实例都是相对于前一个实例布局。
instanceBlueOffset 和 instanceGreenOffset 实现逐步减少蓝色和绿色通道.
好玩的应用在这里
CAReplicatorLayer 的一个实际应用是:反射。
使用 CAReplicatorLayer 并应用一个负比例变换于一个复制图层。就可以创建指定内容视图的镜像图片。这样就创建了一个“反射”的实时效果。
show code
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;
CAScrollLayer
简单介绍一下
CAScrollLayer就是可以显示大图的一小部分。他有一个方法
scrollToPoint:自动适应 bounds 的圆点使图层内容出现在滑动的地方。
CAScrollLayer 不处理边界检查,内容完全可以超出边界。
CAScrollLayer 的头文件中有一个 CALayer 的分类。这个分类中定义了两个方法
- (void)scrollPoint:(CGPoint)p;
- (void)scrollRectToVisible:(CGRect)r;
这两个方法的作用就是在图层树中查找并找到第一个可用的CAScrollLayer。然后滑动它使得指定点成为可视的。
CATiledLayer
CATiledLayer优化了哪方面的需求?
解决在iOS平台进行大图载入和绘制带来的性能问题。比如高像素的图片或者是地图
CATiledLayer可以将大图分解成小片然后把它们按需加载。
开始搞起
首先我们要把一张大图分解成很多个小图。这个过程可以在Mac端进行。
然后我们有了这些小图之后,把CATiledLayer和UIScrollView结合使用。在滑动的时候再加载需要的小图。关键代码写在drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)ctx方法里面。当需要载入新的小图的时候,CATiledLayer就会调用这个方法:
- (void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)ctx
{
//determine tile coordinate
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: @"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的 contentsScale来匹配屏幕像素 。然后把下述代码也进行修改
CGFloat scale = [UIScreen mainScreen].scale;
NSInteger x = floor(bounds.origin.x / layer.tileSize.width * scale);
NSInteger y = floor(bounds.origin.y / layer.tileSize.height * scale);
这个时候大图的尺寸将会以一半的大小显示出来。
AVPlayerLayer
AVPlayerLayer是AVFoundation框架提供的CALayer的子类来显示自定义的内容。
可以使用AVPlayerLayer在iOS上播放视频。是高级接口例如MPMoivePlayer的底层实现。
show Code
AVPlayer *player = [AVPlayer playerWithURL:URL];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
当然。做为CALayer的子类,我们可以对这个图层做圆角、边框、蒙版、阴影等效果。
iOS核心动画(专用图层篇)的更多相关文章
- iOS核心动画高级技巧之图层变换和专用图层(二)
iOS核心动画高级技巧之CALayer(一) iOS核心动画高级技巧之图层变换和专用图层(二)iOS核心动画高级技巧之核心动画(三)iOS核心动画高级技巧之性能(四)iOS核心动画高级技巧之动画总结( ...
- IOS 动画专题 --iOS核心动画
iOS开发系列--让你的应用“动”起来 --iOS核心动画 概览 通过核心动画创建基础动画.关键帧动画.动画组.转场动画,如何通过UIView的装饰方法对这些动画操作进行简化等.在今天的文章里您可以看 ...
- iOS核心动画高级技巧之核心动画(三)
iOS核心动画高级技巧之CALayer(一) iOS核心动画高级技巧之图层变换和专用图层(二)iOS核心动画高级技巧之核心动画(三)iOS核心动画高级技巧之性能(四)iOS核心动画高级技巧之动画总结( ...
- iOS核心动画高级技巧之CALayer(一)
iOS核心动画高级技巧之CALayer(一) iOS核心动画高级技巧之图层变换和专用图层(二)iOS核心动画高级技巧之核心动画(三)iOS核心动画高级技巧之性能(四)iOS核心动画高级技巧之动画总结( ...
- iOS核心动画学习整理
最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一 ...
- iOS 核心动画 Core Animation浅谈
代码地址如下:http://www.demodashi.com/demo/11603.html 前记 关于实现一个iOS动画,如果简单的,我们可以直接调用UIView的代码块来实现,虽然使用UIVie ...
- iOS核心动画高级技巧 - 8
iOS核心动画高级技巧 - 1 iOS核心动画高级技巧 - 2 iOS核心动画高级技巧 - 3 iOS核心动画高级技巧 - 4 iOS核心动画高级技巧 - 5 iOS核心动画高级技巧 - 6 iOS核 ...
- IOS 核心动画之CAKeyframeAnimation - iBaby
- IOS 核心动画之CAKeyframeAnimation - 简单介绍 是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation ...
- iOS核心动画以及UIView动画的介绍
我们看到很多App带有绚丽狂拽的特效,别出心裁的控件设计,很大程度上提高了用户体验,在增加了实用性的同时,也赋予了app无限的生命力.这些华丽的效果很多都是基于iOS的核心动画原理实现的,本文介绍一些 ...
随机推荐
- js MD5加密与 java MD5加密不一致
因为该项目会部署到多台机器,所以需要用字符生成唯一的MD5,但是js生成的MD5和java生成的MD5不一致.经过博主查阅资料发现java生成MD5用的是utf-8的编码,而且js用的是2进制.那我就 ...
- mysql 分组和排序
mysql> select * from table1; +----------+------------+-----+---------------------+ | name_new | t ...
- springMVC开启声明式事务实现操作日志记录
第一步.在applicationContext-mvc.xml开启AOP注解扫描 <aop:aspectj-autoproxy/> 第二步.创建增强类,实现日志记录 @Component ...
- Java获取当天、当前月、当前年(今年)的开始和结束时间戳
最近在做统计相关的功能的时候涉及到了获取当天的开始和结束的时间戳.当月和当年的开始结束时间戳,特此记录,以作备忘. 相关代码 package com.lingyejun.authenticator; ...
- TICK/TIGK运维栈安装运行 docker-compose【下】
InfluxDB 构建Dockerfilevim /opt/influxdb-docker/Dockerfile FROM influxdb COPY influxdb.conf /etc/influ ...
- how does SELECT TOP works when no order by is specified?
how does SELECT TOP works when no order by is specified? There is no guarantee which two rows you ge ...
- Java-Maven(十二):idea多项目:common module进行compiler和install正常,运行domain-perf module提示:Could not resolve dependencies for project
前提: product项目下有三个module,分别是: driver module domain-perf module common module 问题: driver 和 domain-perf ...
- Python3之logging模块浅析
Python3之logging模块浅析 目录 Python3之logging模块浅析 简单用法 日志与控制台同时输出 一个同时输出到屏幕.文件的完成例子 日志文件截取 日志重复打印问题解决 问题分 ...
- kafka发送超大消息设置
最近开发一cdc框架,为了测试极端情况,需要kafka传递100万条数据过去,1个G左右,由于其他环节限制,不便进行拆包(注:测下来,大包走kafka不一定性能更好,甚至可能更低). 测试百万以上的变 ...
- ES6将两个数组合并成一个对象数组
需求 有这么两个数组 let metrodates = [ "2008-01", "2008-02", "2008-03",..ect ]; ...