《Core Animation》-- CALayer基础属性及方法介绍

如图:UIView可以处理触摸事件,但CALayer是不支持交互的(不清楚具体的相应链的)。实际上这些背后关联的图层才是真正用来在屏幕上显示和做动画,UIView仅仅是对它的一个封装,提供了一些iOS类似于处理触摸的具体功能,以及Core Animation底层方法的高级接口。

<四个层级关系>:视图层级、图层树、呈现树和渲染树。

属性介绍

  • Contents:

事实上,你真正要赋值的类型应该是CGImageRef,它是一个指向CGImage结构的指针。UIImage有一个CGImage属性,它返回一个"CGImageRef",如果你想把这个值直接赋值给CALayer的contents,那你将会得到一个编译错误。因为CGImageRef并不是一个真正的Cocoa对象,而是一个Core Foundation类型。可以通过bridged关键字转换。

@property(nullable, strong) id contents;
  • contentMode:
//对应UIView的contentMode.  
@property(copy) NSString *contentsGravity;
  • geometryFlipped:
//决定了一个图层的坐标是否相对于父图层垂直翻转。是为了适配iOS和OS X两种不同坐标系的情况。
@property(getter=isGeometryFlipped) BOOL geometryFlipped;
  • zPosition:
//常用于做CATransform3D变换及更改图层的显示顺序。<不能改变事件传递的顺序>
@property CGFloat zPosition;
  • anchorPointZ:
//在Z轴上描述图层位置的浮点类型
@property CGFloat anchorPointZ;
  • position:

指定了anchorPoint相对于父图层的位置。

//对应UIView的center.
@property CGPoint position;
  • anchorPoint:

锚点,可以理解为固定图层的点。相对于自身坐标系,取值范围0~1,默认(0.5,0.5)。

@property CGPoint anchorPoint;

position和anchorPoint的换算公式:彻底理解position和anchorPoint

position.x = frame.origin.x + anchorPoint.x * bounds.size.width;  
position.y = frame.origin.y + anchorPoint.y * bounds.size.height;
  • contentsScale:

属性定义了寄宿图的像素尺寸和视图大小的比例,默认情况下它是一个值为1.0的浮点数。当设置了contentsGravity属性会有所影响。

//如果contentsScale设置为1.0,将会以每个点1个像素绘制图片。并且把contentsGravity设置为kCAGravityCenter(这个值并不会拉伸图片),那将会有很明显的变化。
@property CGFloat contentsScale
  • contentsRect:

属性允许我们在图层边框里显示寄宿图的一个子域,contentsRect不是按点来计算的,它使用了单位坐标,单位坐标指定在0到1之间,是一个相对值(像素和点就是绝对值)

@property CGRect contentsRect;

其实是一个CGRect,它定义了一个固定的边框和一个在图层上可拉伸的区域。

//单位坐标,定义的区域会被全面拉伸(也就是从四个方向进行放大或者缩小),所'侵占'的地方的视图也会进行相应的拉伸变换。
@property CGRect contentsCenter;
  • masksToBounds:
//等同于UIView的clipsToBounds.
@property BOOL masksToBounds;
  • mask:

是个CALayer类型,有和其他图层一样的绘制和布局属性。它类似于一个子图层,相对于父图层(即拥有该属性的图层)布局,但是它却不是一个普通的子图层。不同于那些绘制在父图层中的子图层,mask图层定义了父图层的部分可见区域。

@property(nullable, strong) CALayer *mask;
  • minificationFilter && magnificationFilter
@property(copy) NSString *minificationFilter;//缩小:
@property(copy) NSString *magnificationFilter;//放大:

--值的介绍:

1。kCAFilterLinear:默认值,采用双线性滤波算法,它在大多数情况下都表现良好。双线性滤波算法通过对多个像素取样最终生成新的值,得到一个平滑的表现不错的拉伸。但是当放大倍数比较大的时候图片就模糊不清了。

2。kCAFilterTrilinear:三线性滤波算法存储了多个大小情况下的图片(也叫多重贴图),并三维取样,同时结合大图和小图的存储进而得到最后的结果。这不仅提高了性能,也避免了小概率因舍入错误引起的取样失灵的问题.

3。kCAFilterNearest:取样最近的单像素点而不管其他的颜色。这样做非常快,也不会使图片模糊。但是,最明显的效果就是,会使得压缩图片更糟,图片放大之后也显得块状或是马赛克严重。(不推荐)。

--总结:

对于比较小的图或者是差异特别明显,极少斜线的大图,最近过滤算法会保留这种差异明显的特质以呈现更好的结果。但是对于大多数的图尤其是有很多斜线或是曲线轮廓的图片来说,最近过滤算法会导致更差的结果。换句话说,线性过滤保留了形状,最近过滤则保留了像素的差异。

  • shouldRasterize:

为了启用shouldRasterize属性,我们设置了图层的rasterizationScale属性。默认情况下,所有图层拉伸都是1.0, 所以如果你使用了shouldRasterize属性,你就要确保你设置了rasterizationScale属性去匹配屏幕,以防止出现Retina屏幕像素化的问题。(info.plist文件中有个全局设置属性:UIViewGroupOpacity)

//组透明效果
@property BOOL shouldRasterize;
  • affineTransform

这里只提供了set和get方法。

- (CGAffineTransform)affineTransform;
- (void)setAffineTransform:(CGAffineTransform)m;

—栗子:

CGAffineTransform  affine = CGAffineTransformMakeRotation(M_PI_4);
blueLayer.affineTransform = affine;

代理

CALayer有一个可选的delegate属性,实现了CALayerDelegate协议,当CALayer需要一个内容特定的信息时,就会从协议中请求。CALayerDelegate是一个非正式协议,其实就是说没有CALayerDelegate @protocol可以让你在类里面引用啦。你只需要调用你想调用的方法,CALayer会帮你做剩下的。(delegate属性被声明为id类型,所有的代理方法都是可选的)。

  • 当需要被重绘时,CALayer会请求它的代理给他一个寄宿图来显示。它通过调用下面这个方法做到的:
- (void)displayLayer:(CALayerCALayer *)layer;
  • 如果代理不实现-displayLayer:方法,CALayer就会转而尝试调用下面这个方法,在调用这个方法之前,CALayer创建了一个合适尺寸的空寄宿图(尺寸由boundscontentsScale决定)和一个Core Graphics的绘制上下文环境,为绘制寄宿图做准备,他作为ctx参数传入。
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

—栗子:

    CALayer * delegateLayer = [CALayer layer];
    [self.view.layer addSublayer:delegateLayer];
    delegateLayer.frame = CGRectMake(50, 100, 300, 400);
    delegateLayer.backgroundColor = [UIColor brownColor].CGColor;
    delegateLayer.delegate = self;//这里需遵循CALayerDelegate协议。

    [delegateLayer display];//这里需要显式地调用了-display。不同于UIView,当图层显示在屏幕上时,CALayer不会自动重绘它的内容。它把重绘的决定权交给了开发者。
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
  //draw a thick red circle
  CGContextSetLineWidth(ctx, 10.0f);
  CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
  CGContextStrokeEllipseInRect(ctx, layer.bounds);
}

—效果:

95187B0D-764B-46CA-B26E-C4E835BD8D03.jpeg

—注意:

尽管我们没有用masksToBounds属性,绘制的那个圆仍然沿边界被裁剪了。这是因为当你使用CALayerDelegate绘制寄宿图的时候,并没有对超出边界外的内容提供绘制支持。

当UIView创建了它的宿主图层时,它就会自动地把图层的delegate设置为它自己,并提供了一个-displayLayer:的实现,那所有的问题就都没了。

当使用寄宿了视图的图层的时候,你也不必实现-displayLayer:-drawLayer:inContext:方法来绘制你的寄宿图。通常做法是实现UIView的-drawRect:方法,UIView就会帮你做完剩下的工作,包括在需要重绘的时候调用-display方法。

其它方法

  • UIView会在初始化的时候调用+layerClass方法,然后用它的返回类型来创建宿主图层。(特别适用,返回的值代表self.layer)
+(Class)layerClass
  • 以下方法可以把定义在一个图层坐标系下的点或者矩形转换成另一个图层坐标系下的点或者矩形.
- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer;//得到layer上的point的点相对于方法调用者的相对point。
- (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;
  • 接受一个在本图层坐标系下的CGPoint,如果这个点在图层frame范围内就返回YES。需要把触摸坐标转换成每个图层坐标系下的坐标,结果很不方便。
- (BOOL)containsPoint:(CGPoint)p;
  • 方法同样接受一个CGPoint类型参数,而不是BOOL类型,它返回图层本身,或者包含这个坐标点的叶子节点图层。这意味着不再需要像使用-containsPoint:那样,人工地在每个子图层变换或者测试点击的坐标。如果这个点在最外面图层的范围之外,则返回nil。
- (nullable CALayer *)hitTest:(CGPoint)p;

—栗子:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint point = [[touches anyObject] locationInView:self.view];
    CALayer *layer = [self.layerView.layer hitTest:point];
    if (layer == self.blueLayer) {

    } else if (layer == self.layerView.layer) {

    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容