CALayer
1.官方解释
The CALayer class manages image-based content(内容) and allows you to perform animations on that content. Layers are often used to provide the backing store(存储器) for views but can also be used without a view to display content. A layer’s main job is to manage the visual content that you provide ++主要目的就是管理那些可见的内容++but the layer itself has visual attributes that can be set, such as a background color, border, and shadow. In addition to managing visual content, the layer also maintains information about the geometry(几何) of its content (such as its position, size, and transform(改变) that is used to present that content on screen. Modifying the properties of the layer is how you initiate animations on the layer’s content or geometry. A layer object encapsulates(囊括) the duration and pacing of a layer and its animations by adopting the CAMediaTiming protocol, which defines the layer’s timing information.
If the layer object was created by a view, the view typically assigns itself as the layer’s delegate automatically, and you should not change that relationship. For layers you create yourself, you can assign(指定) a delegate object and use that object to provide the contents of the layer dynamically and perform other tasks. A layer may also have a layout manager object (assigned to the layoutManager property) to manage the layout of subviews separately.
2.自己的理解
- 1.CALayer(Core Animation Layer),layer是层的意思,所以这是一个核心动画的层,之所以被称作是核心动画,- 2.CALayer包含在QuartzCore框架中,这是一个跨平台的框架,既可以用在iOS中又可以用在Mac OS X中。在使用Core Animation开发动画的本质就是将CALayer中的内容转化为位图从而供硬件操作;
- 3.每一个UIView都有一个root layer,它是由系统创建的,并且self.view.layer是一个只读的属性,也就是说你无法更换这个系统自己创建的layer,你只可以给他增加一个sublayer,然后去对sublayer做各种事情,一个view之所以能够显示东西,就是因为他有layer;
- 4.当利用drawRect:方法绘图的本质就是绘制到了UIView的layer(属性)中,但是在Core Animation中我们操作更多的则不再是UIView而是直接面对CALayer;
- 5.CALayer和UIView的关系如下图,在UIView中有一个layer属性作为根图层,根图层上可以放其他子图层,在UIView中所有能够看到的内容都包含在layer中;
图:(img) - 6.在iOS中CALayer的设计主要是了为了内容展示和动画操作,CALayer本身并不包含在UIKit中,它不能响应事件。由于CALayer在设计之初就考虑它的动画操作功能,CALayer很多属性在修改时都能形成动画效果,这种属性称为“隐式动画属性”。但是对于UIView的根图层而言属性的修改并不形成动画效果,因为很多情况下根图层更多的充当容器的做用,如果它的属性变动形成动画效果会直接影响子图层。
3.layer常用属性的理解和使用详解
(img)
(img)
部分属性的详细解释如下:
1.@property id contents:
An object that provides the contents of the layer,The default value of this property is nil. If you are using the layer to display a static image, you can set this property to the CGImageRef containing the image you want to display. (In OS X 10.6 and later, you can also set the property to an a href="" NSImage /a object.) Assigning a value to this property causes the layer to use your image rather than create a separate backing store.
'' id image = (id)[UIImage imageNamed:@"阿狸头像"].CGImage;
'' self.view.layer.contents = image;
**If the layer object is tied to a view object, you should avoid setting the contents of this property directly.** The interplay between views and layers usually results in the view replacing the contents of this property during a subsequent update.
自己的理解:这个属性的类型被定义为id,意味着它可以是任何类型的对象。在这种情况下,你可以给contents属性赋任何值,你的app仍然能够编译通过。但是,在实践中,如果你给contents赋的不是CGImage,那么你得到的图层将是空白的。
contents这个奇怪的表现是由Mac OS的历史原因造成的。它之所以被定义为id类型,是因为在Mac OS系统上,这个属性对CGImage和NSImage类型的值都起作用。如果你试图在iOS平台上将UIImage的值赋给它,只能得到一个空白的图层。一些初识Core Animation的iOS开发者可能会对这个感到困惑。
头疼的不仅仅是我们刚才提到的这个问题。事实上,你真正要赋值的类型应该是CGImageRef,它是一个指向CGImage结构的指针。UIImage有一个CGImage属性,它返回一个"CGImageRef",如果你想把这个值直接赋值给CALayer的contents,那你将会得到一个编译错误。因为CGImageRef并不是一个真正的Cocoa对象,而是一个Core Foundation类型。
尽管Core Foundation类型跟Cocoa对象在运行时貌似很像(被称作toll-free bridging),它们并不是类型兼容的,不过你可以通过bridged关键字转换。如果要给图层的寄宿图赋值,你可以按照以下这个方法:
layer.contents = (_bridge id)image.CGImage;
2.@property CGRect contentsRect
The rectangle, in the unit coordinate space, that defines the portion of the layer’s contents that should be used. Animatable.
ex:
效果图1:(img)
修改 contentrect属性:
''UIImageView *view1 = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
''view1.layer.contentsRect = CGRectMake(0, 0, 1, 0.5);//我只想看到你y方向的一半,从0那个位置开始
''view1.image = [UIImage imageNamed:@"阿狸头像"];
''[self.view addSubview:view1];
效果图2:(img)
若对rect进行修改为(0,0.5,1,0.5)
''view1.layer.contentsRect = CGRectMake(0, 0.5, 1, 0.5);
效果图3:(img)
Defaults to the unit rectangle (0.0, 0.0, 1.0, 1.0). If pixels outside the unit rectangle are requested, the edge pixels of the contents image will be extended outwards.(如果在矩形单元之外,仍然要求显示像素,那么图片的边缘像素就会被拉伸)
''view1.layer.contentsRect = CGRectMake(0, 0, 2, 2);//我想要看到你这个图片两倍的面积那么大,结果会对边界进行像素的拉伸,基本上就毁掉了
效果图4:(img)
3.anchorPoint+position+bounds = frame
We usually use the anchorPoint with the property “position” or we make a rotation animation,the anchorPoint is the center on point,and the layer will rotation around the point.And when we creat a new layer without set the frame,we need to set the bounds+position+anchorPoint,we get size from bounds,and get the position from “position”+”anchorPiont”,the position is in super layer coordinate system,and the anchorPoint is in the created layer itself,we make the two points superposition(重合),this is how we confirm the created layer’s position.
When we use a frame to specified a rectangle,it is supposed as (100, 100, 200, 200),it means the “position” is (100, 100),the anchorPoint is (0, 0),warning,when the layer is rotating,the center point is (0.5, 0.5),cause the default anchorPoint is(0.5, 0.5),this is for scale;
The main difference between frame and another three properties is we cannot get invisible animation with frame,so we usually use bounds+position+anchorPoint instead.
相同的position,不同的anchorPoint,不同的位置(img)
实例:
使用frame
''CALayer *layer = [CALayer layer];
''layer.backgroundColor = [UIColor redColor].CGColor;
''layer.frame = CGRectMake(0, 0, 100, 100);
''[self.view.layer addSublayer:layer];
效果图1:(img)
使用position+anchorPoint+bounds
''CALayer *layer = [CALayer layer];
''layer.backgroundColor = [UIColor redColor].CGColor;
''//利用这三个属性来定义一个layer的位置
''layer.position = CGPointMake(0, 0);
''layer.bounds = CGRectMake(0, 0, 100, 100);
''layer.anchorPoint = CGPointMake(0, 0);
''
''[self.view.layer addSublayer:layer];
效果图2:(img)
如果不设置anchorPoint,那么这个值默认就是(0.5, 0.5),就会只显示1/4.
4.shadow
''CALayer *layer = [CALayer layer];
''layer.backgroundColor = [UIColor redColor].CGColor;
''layer.frame = CGRectMake(0, 0, 100, 100);
''layer.shadowColor = [UIColor blueColor].CGColor;
''layer.shadowOffset = CGSizeMake(10, 1);//向右偏移10,向下偏移1
''layer.shadowOpacity = 1;
''//layer.shadowPath 默认返回一个跟他一模一样的东西
''layer.shadowRadius = 10;
''[self.view.layer addSublayer:layer];
效果图:(img)
5.mask and maskToBounds
mask:
An optional layer whose alpha channel is used to mask the layer’s content.
The layer’s alpha channel determines how much of the layer’s content and background shows through. Fully or partially opaque pixels allow the underlying content to show through but fully transparent pixels block that content.
The default value of this property is nil nil. When configuring a mask, remember to set the size and position of the mask layer to ensure it is aligned properly with the layer it masks.
首先,mask是蒙板的意思,它的实质是一个layer,我们使用的是layer的frame,也就是他的位置和形状,用它的位置和形状来创建一个可见通道,当你给一个添加了mask,那么只有在这个mask之下的部分才能被看到。默认情况下layer是没有蒙板的,当你设置一个蒙板的时候,一定要设置尺寸和位置,要不然你啥也看不到。
关于mask的位置,mask相当于是layer的sublayer,那么它的位置是相对于layer的。
通过两个layer的组合,我们可以创造出一些比较奇怪的形状。
实例:
''CALayer *layer = [CALayer layer];
''layer.backgroundColor = [UIColor blueColor].CGColor;
''layer.frame = CGRectMake(100, 100, 100, 100);
'' //mask蒙板
''CALayer *mask = [[CALayer alloc] init];
''mask.backgroundColor = [UIColor blackColor].CGColor;
''mask.frame = CGRectMake(0, 0, 50, 50);
''mask.cornerRadius = mask.frame.size.width/2;
''layer.mask = mask;
''[self.view.layer addSublayer:layer];
给layer添加一个蒙板,我们看到的是蒙板后边的东西就(img)
效果图:(img)
maskToBounds:
A Boolean indicating whether sublayers are clipped to the layer’s bounds.
When the value of this property is YES, Core Animation creates an implicit clipping mask that matches the bounds of the layer and includes any corner radius effects. If a value for the mask property is also specified, the two masks are multiplied to get the final mask value.
The default value of this property is NO.
理解这个属性要抓住两个要点:第一个是它会创建一个mask,这个mask跟layer一模一样,第二个是,这个mask只对layer本身的sublayers起作用。
实例:
''CALayer *layer = [CALayer layer];
''layer.backgroundColor = [UIColor blueColor].CGColor;
''layer.frame = CGRectMake(100, 100, 100, 100);
''CALayer *layer1 = [CALayer layer];
''layer1.backgroundColor = [UIColor redColor].CGColor;
''layer1.frame = CGRectMake(50, 0, 100, 100);
''layer1.cornerRadius = layer1.frame.size.width/2;
''//把layer1变成layer的sublayer,这样masktobounds就可以对他起作用
''[layer addSublayer:layer1];
''layer.masksToBounds = YES;
''[self.view.layer addSublayer:layer];
效果图:(img)
稍作更改,layer1.frame = CGRectMake(0, 0, 100, 100);
效果图:(img)