在iOS中都会牵扯到图形转换,动画效果,添加视图,等等的一系列问题,在设计页面,设计图形,添加动画的时候都会使用到这个知识。
简单的说他就是视图的图层,但又不是视图,因为视图可以和用户交互,添加响应事件,添加视图等等,但是CALayer并不可以添加响应事件等等,它只是一个视图的图层,就是这个图片的显示层,展示层,只能够显示内容,比如展示背景颜色,展示图片,设置边框,等等。
- UIView上面的rootLayer 发生改变的话 子图层也会发生变化
- 如果想要改变 button的视图形状边框等,要改变的不止有一个视图 改变的只是其中一个视图的rootLayer 它会显示出显示未被裁切的边框
- rootLayer上面没有动画效果
- CALayer发生改变 子图层不会跟随发生改变 自带动画效果(当改变属性值的时候) 隐式动画
理解了CALayer之后就可以大致的有一个了解,有个要使用的方向,而且单独对图层做设计修改的时候功能也会比以前多很多,而且当你改变他的图层数值的时候,CALayer是自带隐式动画效果的
接下来看一个图来大概了解下视图的图层关系,下面是我某一个页面的3D图,不得不说Xcode的强大
在左边我们可以详细看到他们的图层是怎么样嵌套的,当你选中一个图层的时候你也可以在上面看到他的所有父视图,或者说在他之前有几层图层,分别是什么,当你对一个视图进行处理的时候,打算处理他的哪一个图层,都很重要。
如果你只处理了一层,比如我为了美观,我想把上图collectionView上面的cell设置了这个属性
cell.layer.cornerRadius = 10;
他就会有一点圆边,让用户感觉上至少比方方正正的好看很多,但是我cell上面还有一层imageView和label,他们都在contentView上面,在这两个属性都为空的时候,cell没有问题,但一旦我设置了图片,而且是填满状态的,显示图片是没有问题,但是你会发现这个cell他又变成方方正正的了,💢这难免会让人很烦躁,有时候确实会因为各种原因头疼,甚至因此卡住,或者放弃这个效果,白白浪费了一段时间。
感觉有点像打广告的。。所以你要设置的时候要清楚的知道自己要对哪一个图层进行处理,在这里我们只要再给他的ImageView层处理一下layer就可以了
cell.imageView.layer.cornerRadius = 10;
//裁切内容的尺寸
cell.imageView.layer.masksToBounds = YES;
接下来说一下图层的一些属性,可修改的一些属性
- bounds 边境范围
- position 中心点
- zPosition z轴中心点
- anchorPoint 锚点 ✮✮✮✮✮
- 锚点 默认锚点是与中心店重合 锚点的最小值是0,0最大值1,1 默认值是0.5,0.5
- 当视图 改变的时候 是以锚点为基准去改变
- 锚点的值与位置
- anchorPointZ Z轴锚点
- transform 转换形态
- frame NO. Animatable 坐标
- hidden 隐藏
- doubleSided 图层背面是否显示
- geometryFlipped 翻转 颠倒
- masksToBounds 裁切边境
- contents 内容
- opaque 不透明度
- allowsEdgeAntialiasing 是否使用 变形后的抗锯齿
- backgroundColor 背景颜色
- borderWidth 边框宽
- borderColor 边框颜色
- opacity 不透明度
- shadowColor 阴影颜色
- shadowOpacity 阴影不透明度
- rasterizationScale 防止Retina屏幕像素化
- shadowOffset 阴影偏移量
- shadowRadius 阴影的半径
通过设置这些属性都可以让视图的形态等发生改变,要注意在给CALayer一些属性赋值的时候,他需要的值得类型都是一些特殊类型的值
比如我们之前在给View的transform赋值的时候使用的都是CGAffineTransform类型的,而给CALayer的transform赋值的时候使用使用的是CATransform3D类型的值,包括改变背景颜色也是使用的CGColor,图片是CGImageRef所以使用的时候要注意。
在给他们修改属性的时候,因为CALayer自带隐式动画,所以在触发事件等改变他的属性的时候都会自带动画效果。
在下面要具体说一下CALayer里面的锚点属性,也是动画,视图效果使用最重要的一个属性
大家如果有用过UIView的一些animation的基础动画的时候可能会知道,没用过也没关系,你肯定知道移动视图都是调整视图的center值来做到使视图移动到另外一个位置,设置bounds来放大或缩小一个视图。这里我们不重点说这个。
在这里锚点和视图的center值有点类似,也是通过知道他的中心点,来设置这个中心点,来改变他的位置,不过在这里我们不用中心点了,用的就是锚点来替代了这个点,他可以让视图以任意点为挪动点,比如,一个长长的汽车在行驶,汽车上面的人的位置都是固定不变的,你可以通过改变汽车的中心点来让汽车移动,也可以通过某一个人的位置的改变来改变汽车的位置,比如我现在想让这个汽车通过一个山洞
比如星星是司机,在这里我可以通过这个司机的位置,把司机的X增加一定的数值来让这个车通过这个山洞,和通过改变中心点是一个道理,只不过是这个中心点变了,变成了我们定义的一个锚点。也可以理解成把牛栓在树上,他怎么跑也跑不出这个点,以这个点为移动点来做动作。
理解了这个点的含义,就能做很多事情,比如有些动画就是通过固定锚点来让视图做一些动作
原谅我做不出动图T T,没有美工,在这里我设置图片的旋转就是让他转动半个圆,但是我把它的锚点设置成了他的右下角,所以他会以右下角来转动。
我们简单的写一个实例的layer
我们把CALayer定义成一个全局变量
{
CALayer *layer;
}
layer = [CALayer layer];
layer.frame = CGRectMake(0, 0, 100, 100);
layer.backgroundColor = [UIColor colorWithRed:1.000 green:0.607 blue:0.468 alpha:1.000].CGColor;
//在这里注意我们要添加的是一个layer所以要把它添加到我们要修改视图的layer上面
[self.view.layer addSublayer:layer];
然后我们写一个touchBegan的方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGFloat width = CGRectGetWidth(layer.bounds)!=100?100:25;
layer.bounds = CGRectMake(0, 0, width, width);
layer.cornerRadius = layer.cornerRadius !=50 ? 50:0;
layer.position = [touch locationInView:self.view];
}
在这里我们也简单写一个锚点的使用,我们继续定义一个CALayer
@property (nonatomic,strong)CALayer *pointLayer;
self.pointLayer.anchorPoint = CGPointMake(0.5 , 0.9);
self.pointLayer.contents = (id)[UIImage imageNamed:@"要旋转的图片"].CGImage;
- (CALayer *)pointLayer{
if (_pointLayer) {
return _pointLayer;
}
_pointLayer = [CALayer layer];
[self.view.layer addSublayer:_pointLayer];
_pointLayer.bounds = CGRectMake(0, 0, 20, 160);
_pointLayer.position = self.view.center;
return _pointLayer;
}
我们这个图片是一个宽20,高160的图片,我还是放一个图吧,免得被骂。。
嗯。。大概就是这个形状,好的,锚点是以图层的比例来定义的,我定义的是X轴比例0.5,Y比例0.9,也就是说,这个点大概在X是一半,Y是0.9,就是把这个图从上到下分成10份,他在第9份那个位置,大概在如图位置,咳咳。。然后,我们让他来进行一个旋转,正常的旋转应该都是以中心点来旋转,大概画面就像孙悟空耍金箍棒一样,以中心来旋转
我们来设置一个方法通过定时器来调用它
- (void)start{
// NSCalendar日历的一个类,可以通过它获得年月日 时分秒
// NSCalendar
// NSDateComponents 组件 fromDate 获得哪个日期的组件
NSCalendar *calendar = [NSCalendar currentCalendar];
// @property NSInteger hour;
// @property NSInteger minute;
// @property NSInteger second;
NSDateComponents *components = [calendar components:NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:[NSDate date]];
float s = components.second * 6;
//在layer上面添加transform使用的都是CATransform3D
//X Y Z是设置绕哪个轴来旋转的 第一个值是旋转的角度
self.pointLayer.transform = CATransform3DMakeRotation(s, 0, 0, 1);
}
然后我们在viewDidLoad添加一个定时器
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(start) userInfo:nil repeats:YES];
现在他就可以绕点来进行旋转了
具体每个属性都可以自己试一下他的效果,然后发一个有助于理解锚点的demo
最后说一下iOS的核心动画也是通过这个图层来实现的,下次把链接贴上
再贴上一个图层效果的一些处理处理图层特效