CALayer的简单介绍
1.UIView是calyer的代理
2. 简单介绍
、简单介绍
在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView。
其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层
@property(nonatomic,readonly,retain) CALayer *layer;
当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示
换句话说,UIView本身不具备显示的功能,拥有显示功能的是它内部的图层。
3.CALayer的基本属性
代码如下
// 控制器的view的颜色
self.view.backgroundColor = [UIColor lightGrayColor];
//设置view1的位置和大小
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
//设置View1的背景颜色
view1.backgroundColor = [UIColor redColor];
// 1>边框
view1.layer.borderWidth = 10;
view1.layer.borderColor = [UIColor whiteColor].CGColor;//边框的颜色
// 2>阴影
view1.layer.shadowColor = [UIColor blueColor].CGColor;//阴影的颜色
// view1.layer.shadowOffset = CGSizeMake(50, 50);
view1.layer.shadowOpacity = 1;//向同于alpah 透明度
view1.layer.shadowRadius = 50; //设置圆角,越大越模糊
// 3>圆角
view1.layer.cornerRadius = 50;//设置圆角图片
view1.layer.masksToBounds = YES;//剪切
// 4>bounds
view1.layer.bounds = CGRectMake(0, 0, 200, 200);//layer的大小
// 5>postion属性和view.center的关系(默认情况下)
view1.layer.position = CGPointMake(100, 100);//位置
// 6>设置内容(图片)
view1.layer.contents = (__bridge id)([UIImage imageNamed:@"me"].CGImage);
// 7>获取图片*
[self.view
addSubview:view1];//添加
4.手动创建layer
代码如下:
//
创建layer对象
CALayer* layer = [[CALayer alloc] init];
layer.bounds = CGRectMake(0, 0, 100, 100); // 大小
layer.position = CGPointMake(150, 150); // 位置
layer.backgroundColor = [UIColor redColor].CGColor; // 颜色
// layer.opacity = 0.5; // 透明度
// 把创建的layer添加到控制器view的layer中
[self.view.layer addSublayer:layer];
//赋值回去启动全局
self.layer = layer;
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
CALayer* layer = [[CALayer alloc] init];
layer.bounds = CGRectMake(0, 0, 100, 100); // 大小
layer.position = CGPointMake(150, 150); // 位置
layer.backgroundColor = [UIColor redColor].CGColor; // 颜色
// layer.opacity = 0.5; // 透明度
// 把创建的layer添加到控制器view的layer中
[self.view.layer addSublayer:layer];
//赋值回去启动全局
self.layer = layer;
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
//
如何禁用隐式动画
[CATransaction begin]; // 开启事务;
[CATransaction setDisableActions:YES]; // 禁用隐式动画
// 获取触摸对象
UITouch* t = touches.anyObject;
// 获取手指的位置
CGPoint p = [t locationInView:t.view];
// 让layer的位置 跑到手指的位置上来
self.layer.position = p;
[CATransaction commit]; // 提交事务
[CATransaction begin]; // 开启事务;
[CATransaction setDisableActions:YES]; // 禁用隐式动画
// 获取触摸对象
UITouch* t = touches.anyObject;
// 获取手指的位置
CGPoint p = [t locationInView:t.view];
// 让layer的位置 跑到手指的位置上来
self.layer.position = p;
[CATransaction commit]; // 提交事务
控制器的根layer没有隐是动画,layer可以创建很多个,每一个小的layer都会有隐式动画
证明::
创建的一个小的layer
CALayer
*layer =[[CALayeralloc]init];
layer.position = CGPointMake(100, 100);
layer.bounds = CGRectMake(0, 0, 200, 200);
layer.backgroundColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:layer];
self.layer = layer;
// [self test1];
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
// 获取触摸对象
UITouch* t = touches.anyObject;
// 获取位置
CGPoint p = [t locationInView:t.view];
// 让layer的位置等于手指的位置
self.layer.position
= p;
view的根layer是没有隐式动画的
self.view.backgroundColor
= [UIColor
lightGrayColor];
//View的大小
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
//View的背景颜色
view1.backgroundColor = [UIColor redColor];
//赋值回去
self.layer = view1.layer;
// 1>边框
view1.layer.borderWidth = 10;
view1.layer.borderColor = [UIColor whiteColor].CGColor;
// 2>阴影
view1.layer.shadowColor = [UIColor blueColor].CGColor;
// view1.layer.shadowOffset = CGSizeMake(50, 50);
view1.layer.shadowOpacity = 1;
view1.layer.shadowRadius = 50;
// 3>圆角
view1.layer.cornerRadius = 50;
view1.layer.masksToBounds = YES;
// 4>bounds
view1.layer.bounds = CGRectMake(0, 0, 200, 200);
// 5>postion属性和view.center的关系(默认情况下)
view1.layer.position = CGPointMake(100, 100);
// 6>设置内容(图片)
//View的大小
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
//View的背景颜色
view1.backgroundColor = [UIColor redColor];
//赋值回去
self.layer = view1.layer;
// 1>边框
view1.layer.borderWidth = 10;
view1.layer.borderColor = [UIColor whiteColor].CGColor;
// 2>阴影
view1.layer.shadowColor = [UIColor blueColor].CGColor;
// view1.layer.shadowOffset = CGSizeMake(50, 50);
view1.layer.shadowOpacity = 1;
view1.layer.shadowRadius = 50;
// 3>圆角
view1.layer.cornerRadius = 50;
view1.layer.masksToBounds = YES;
// 4>bounds
view1.layer.bounds = CGRectMake(0, 0, 200, 200);
// 5>postion属性和view.center的关系(默认情况下)
view1.layer.position = CGPointMake(100, 100);
// 6>设置内容(图片)
view1.layer.contents
= (__bridge
id)([UIImage
imageNamed:@"me"].CGImage);
[self.view addSubView
:view];
实现效果:
2.layer的transform属性
1.首先创建一个layer对象
// 创建layer对象
CALayer* layer = [[CALayer alloc] init];
self.layer = layer;
layer.bounds = CGRectMake(0, 0, 100, 100); // 大小
layer.position = CGPointMake(150, 150); // 位置
layer.backgroundColor = [UIColor redColor].CGColor; // 颜色
// layer.opacity = 0.5; // 透明度
layer.contents = (__bridge id)([UIImage imageNamed:@"me"].CGImage);
// 把创建的layer添加到控制器view的layer中
[self.view.layer
addSublayer:layer];
1.旋转CATransform3DRotate
- (void)touchesBegan:(NSSet*)touches
withEvent:(UIEvent*)event
{
// 旋转
{
// 旋转
// self.layer.transform = CATransform3DRotate(self.layer.transform, M_PI_4, 0, 0, 1);
2.缩放CATransform3DScale
//
缩放
(z
无效)
// self.layer.transform = CATransform3DScale(self.layer.transform, 1, 1, 0.5);
3.平移CATransform3DTranslate
//
平移
(z
无效)
self.layer.transform
=
CATransform3DTranslate(self.layer.transform,
0,
0,
100);
五.时钟练习
代码如下:
#import
"ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) CALayer* second;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 控制器的背景颜色
self.view.backgroundColor = [UIColor orangeColor];
// 创建一个clock的layer
CALayer* clock = [[CALayer alloc] init];
// 位置
clock.position = CGPointMake(200, 200);
// 大小
clock.bounds = CGRectMake(0, 0, 200, 200);
// 内容
clock.contents = (__bridge id)([UIImage imageNamed:@"clock"].CGImage);
// 圆角
clock.cornerRadius = 100;
clock.masksToBounds = YES;
// 创建一个指针
CALayer* second = [[CALayer alloc] init];
// 位置
second.position = clock.position;
// 大小
second.bounds = CGRectMake(0, 0, 2, 100);
// 颜色
second.backgroundColor = [UIColor redColor].CGColor;
// 定位点 锚点
second.anchorPoint = CGPointMake(0.5, 0.8);
// 把表和针添加到控制器view的layer上
[self.view.layer addSublayer:clock];
[self.view.layer addSublayer:second];
//赋值回去,锁定全局
self.second = second;
//让时钟为0开始
[self timeChange];
//一个做为layer的计时器
CADisplayLink* link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timeChange)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)timeChange
{
//一圈
CGFloat angle = 2 * M_PI / 60;
// 2.NSCalendar
NSDate* date = [NSDate date];
NSCalendar* cal = [NSCalendar currentCalendar];
// 秒
CGFloat secondFloat = [cal component:NSCalendarUnitSecond fromDate:date];
// 毫秒
CGFloat secondFloat1 = [cal component:NSCalendarUnitNanosecond fromDate:date];
// 以毫秒去旋转
secondFloat = secondFloat + secondFloat1 * 0.000000001;
//想用layer的cgaff的属性就得用affineTransform
self.second.affineTransform = CGAffineTransformMakeRotation(secondFloat * angle);
@interface ViewController ()
@property (weak, nonatomic) CALayer* second;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 控制器的背景颜色
self.view.backgroundColor = [UIColor orangeColor];
// 创建一个clock的layer
CALayer* clock = [[CALayer alloc] init];
// 位置
clock.position = CGPointMake(200, 200);
// 大小
clock.bounds = CGRectMake(0, 0, 200, 200);
// 内容
clock.contents = (__bridge id)([UIImage imageNamed:@"clock"].CGImage);
// 圆角
clock.cornerRadius = 100;
clock.masksToBounds = YES;
// 创建一个指针
CALayer* second = [[CALayer alloc] init];
// 位置
second.position = clock.position;
// 大小
second.bounds = CGRectMake(0, 0, 2, 100);
// 颜色
second.backgroundColor = [UIColor redColor].CGColor;
// 定位点 锚点
second.anchorPoint = CGPointMake(0.5, 0.8);
// 把表和针添加到控制器view的layer上
[self.view.layer addSublayer:clock];
[self.view.layer addSublayer:second];
//赋值回去,锁定全局
self.second = second;
//让时钟为0开始
[self timeChange];
//一个做为layer的计时器
CADisplayLink* link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timeChange)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)timeChange
{
//一圈
CGFloat angle = 2 * M_PI / 60;
// 2.NSCalendar
NSDate* date = [NSDate date];
NSCalendar* cal = [NSCalendar currentCalendar];
// 秒
CGFloat secondFloat = [cal component:NSCalendarUnitSecond fromDate:date];
// 毫秒
CGFloat secondFloat1 = [cal component:NSCalendarUnitNanosecond fromDate:date];
// 以毫秒去旋转
secondFloat = secondFloat + secondFloat1 * 0.000000001;
//想用layer的cgaff的属性就得用affineTransform
self.second.affineTransform = CGAffineTransformMakeRotation(secondFloat * angle);
}
实现效果:
六核心动画
1.基本动画CABasicAnimation
创建一个layer
super
viewDidLoad];
// 创建layer
CALayer* layer = [[CALayer alloc] init];
layer.backgroundColor = [UIColor redColor].CGColor; // 颜色
layer.position = CGPointMake(200, 200); // 位置
layer.bounds = CGRectMake(0, 0, 100, 100); // 大小
// 添加到控制器view的layer上
// 创建layer
CALayer* layer = [[CALayer alloc] init];
layer.backgroundColor = [UIColor redColor].CGColor; // 颜色
layer.position = CGPointMake(200, 200); // 位置
layer.bounds = CGRectMake(0, 0, 100, 100); // 大小
// 添加到控制器view的layer上
[self.view.layer
addSublayer:layer];
//当屏幕点击的时候
- (void)touchesBegan:(NSSet*)touches
withEvent:(UIEvent*)event
{
// 基本动画
// 1.创建核心动画的对象
CABasicAnimation* anim = [[CABasicAnimation alloc] init];
// 2.设置核心动画的操作
anim.keyPath = @"transform.rotation";
// anim.fromValue = @(100); // 从哪
// anim.toValue = @(300); // 到哪
anim.byValue = @(M_PI_4);//值
// 动画完毕以后不回到原来的位置
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
// 3.添加到layer上
[self.layer addAnimation:anim forKey:nil];
{
// 基本动画
// 1.创建核心动画的对象
CABasicAnimation* anim = [[CABasicAnimation alloc] init];
// 2.设置核心动画的操作
anim.keyPath = @"transform.rotation";
// anim.fromValue = @(100); // 从哪
// anim.toValue = @(300); // 到哪
anim.byValue = @(M_PI_4);//值
// 动画完毕以后不回到原来的位置
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
// 3.添加到layer上
[self.layer addAnimation:anim forKey:nil];
}
//关键帧动画CAKeyframeAnimation
代码如下:
// 关键帧动画
// 1.创建对象
CAKeyframeAnimation* anim = [[CAKeyframeAnimation alloc] init];
// 2.操作
anim.keyPath = @"position";
NSValue* v1 = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
NSValue* v2 = [NSValue valueWithCGPoint:CGPointMake(150, 50)];
NSValue* v3 = [NSValue valueWithCGPoint:CGPointMake(50, 150)];
NSValue* v4 = [NSValue valueWithCGPoint:CGPointMake(150, 150)];
anim.values = @[ v1, v2, v3, v4 ];
anim.duration = 5; // 设置时间
// 补间动画
// 动画完毕以后不回到原来的位置
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
// 3.添加
[self.layer
addAnimation:anim
forKey:nil];
2.第二种,根据图形
{
// 关键帧动画
// 1.创建对象
CAKeyframeAnimation* anim = [[CAKeyframeAnimation alloc] init];
// 2.操作
anim.keyPath = @"position";
// 用画弧的方式 画圆
// UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2 * M_PI clockwise:1];
// 用椭圆的方式 画圆
UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 100, 100)];
anim.path = path.CGPath;
anim.duration = 3;
anim.repeatCount = INT_MAX; // 重复次数
// 补间动画
// 动画完毕以后不回到原来的位置
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
// 3.添加
[self.layer addAnimation:anim forKey:nil];
// 关键帧动画
// 1.创建对象
CAKeyframeAnimation* anim = [[CAKeyframeAnimation alloc] init];
// 2.操作
anim.keyPath = @"position";
// 用画弧的方式 画圆
// UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2 * M_PI clockwise:1];
// 用椭圆的方式 画圆
UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 100, 100)];
anim.path = path.CGPath;
anim.duration = 3;
anim.repeatCount = INT_MAX; // 重复次数
// 补间动画
// 动画完毕以后不回到原来的位置
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
// 3.添加
[self.layer addAnimation:anim forKey:nil];
}
第三种.关键帧动画,是由每个的帧来运动的,使用椭圆都会停顿,因为它的四个帧是矩形
代码如下:
// -----------------------------------------
// 关键帧动画
// 1.创建对象
CAKeyframeAnimation* anim = [[CAKeyframeAnimation alloc] init];
// 2.操作
anim.keyPath = @"position";
// 用画弧的方式 画圆
// UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2 * M_PI clockwise:1];
// 用椭圆的方式 画圆
UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 100, 100)];
anim.path = path.CGPath;
anim.duration = 3;
anim.repeatCount = INT_MAX; // 重复次数
// 补间动画
// 动画完毕以后不回到原来的位置
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
// 3.添加
[self.layer addAnimation:anim forKey:nil];
// -----------------------------------------
// -----------------------------------------
// 关键帧动画
// 1.创建对象
CAKeyframeAnimation* anim1 = [[CAKeyframeAnimation alloc] init];
// 2.操作
anim1.keyPath = @"position";
// 用画弧的方式 画圆
// UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2 * M_PI clockwise:1];
// 用椭圆的方式 画圆
UIBezierPath* path1 = [UIBezierPath bezierPathWithRect:CGRectMake(100, 100, 100, 100)];
anim1.path = path1.CGPath;
anim1.duration = 3;
anim1.repeatCount = INT_MAX; // 重复次数
// 补间动画
// 动画完毕以后不回到原来的位置
anim1.fillMode = kCAFillModeForwards;
anim1.removedOnCompletion = NO;
// 3.添加
[self.layer1 addAnimation:anim1 forKey:nil];
// 关键帧动画
// 1.创建对象
CAKeyframeAnimation* anim = [[CAKeyframeAnimation alloc] init];
// 2.操作
anim.keyPath = @"position";
// 用画弧的方式 画圆
// UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2 * M_PI clockwise:1];
// 用椭圆的方式 画圆
UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 100, 100, 100)];
anim.path = path.CGPath;
anim.duration = 3;
anim.repeatCount = INT_MAX; // 重复次数
// 补间动画
// 动画完毕以后不回到原来的位置
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
// 3.添加
[self.layer addAnimation:anim forKey:nil];
// -----------------------------------------
// -----------------------------------------
// 关键帧动画
// 1.创建对象
CAKeyframeAnimation* anim1 = [[CAKeyframeAnimation alloc] init];
// 2.操作
anim1.keyPath = @"position";
// 用画弧的方式 画圆
// UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2 * M_PI clockwise:1];
// 用椭圆的方式 画圆
UIBezierPath* path1 = [UIBezierPath bezierPathWithRect:CGRectMake(100, 100, 100, 100)];
anim1.path = path1.CGPath;
anim1.duration = 3;
anim1.repeatCount = INT_MAX; // 重复次数
// 补间动画
// 动画完毕以后不回到原来的位置
anim1.fillMode = kCAFillModeForwards;
anim1.removedOnCompletion = NO;
// 3.添加
[self.layer1 addAnimation:anim1 forKey:nil];
// -----------------------------------------
五,组动画,是由两个动画合并的
组动画:CAAnimationGroup
代码如下 :
// 1.创建对象
CAAnimationGroup* group = [[CAAnimationGroup alloc] init];
// 2.操作
// ----- 1.
// 基本动画
// 1.创建核心动画的对象
CABasicAnimation* anim = [[CABasicAnimation alloc] init];
// 2.设置核心动画的操作
anim.keyPath = @"transform.rotation";
// anim.fromValue = @(100); // 从哪
// anim.toValue = @(300); // 到哪
anim.byValue = @(M_PI * 2 * 50);
// ----- 2.
// 关键帧动画
// 1.创建对象
CAKeyframeAnimation* anim1 = [[CAKeyframeAnimation alloc] init];
// 2.操作
anim1.keyPath = @"position";
// 用画弧的方式 画圆
UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:50 startAngle:0 endAngle:2 * M_PI clockwise:1];
anim1.path = path.CGPath;
group.animations = @[ anim1, anim ];//添加到组动画去
group.repeatCount = INT_MAX; // 重复次数
group.duration = 3;
// 3.添加
[self.layer
addAnimation:group
forKey:nil];
实现效果:
六:转场动画
代码如下
- (IBAction)swipe:(UISwipeGestureRecognizer*)sender
{
self.imageName++;
if (self.imageName == 5) {
self.imageName = 0;
}
UIImage* image = [UIImage imageNamed:[NSString stringWithFormat:@"%d", self.imageName + 1]];
CATransition* anim = [[CATransition alloc] init];
anim.type = @"cameraIrisHollowOpen";
// 判断左右
if (sender.direction == UISwipeGestureRecognizerDirectionLeft) {
// 左
self.imageView.image = image;
anim.subtype = kCATransitionFromRight;
}
else {
// 右
self.imageView.image = image;
anim.subtype = kCATransitionFromLeft;
}
[self.imageView.layer addAnimation:anim forKey:nil];
}
样式:
九:小画板案例
1.布局界面
2.画线
- (UIBezierPath*)path
{
if (!_path) {
_path = [UIBezierPath bezierPath];
}
return _path;
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
// 获取触摸对象
UITouch* t = touches.anyObject;
// 获取手指的位置
CGPoint p = [t locationInView:t.view];
// 移动到到手指点击时候的位置
[self.path moveToPoint:p];
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
// 获取触摸对象
UITouch* t = touches.anyObject;
// 获取手指的位置
CGPoint p = [t locationInView:t.view];
// 画线到手指移动时候的位置
[self.path addLineToPoint:p];
// 重绘
[self setNeedsDisplay];
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
[self.path stroke];
}