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 =[[
CALayer
alloc
]
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];
}