核心动画详细阐述

一.系统创建的CALayer
(1) CALayer的简单介绍

  • 1.在iOS中,你能看的见摸得着的东西基本上都是UIView,比如一个按钮,一个文本标签,一个文本输入框,一个图标等等,这些都是UIView,

  • 2.UIView能够显示在屏幕上完全是因为它内部的一个图层

  • 3.在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIViewlayer属性可以访问这个层

    @property(nonatomic,readonly,retain) CALayer *layer;
    
  • 4.当UIView需要显示到屏幕上时,会调用drawRect方法进行绘图,并且会将所有的内容绘制在自己的图层上,绘制完毕后,系统会将图层拷贝到屏幕上,于是进完成了UIView的显示

  • 5.换句话说,UIView本身不具备显示的功能,是它内部才有显示功能

(2).CALayer的基本使用

通过操作CALayer对象,可以方便地调整UIView的一些外观属性,比如:

  • 1.阴影
    Opacity :不透明度(不透明度只要大于1就说明是有阴影的)

  • 2.圆角大小

  • 3.边框宽度和颜色
    ...........

  • 还可以给图层添加动画,来实现一些比较炫酷的动画效果

阴影的展示

简单的代码展示

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

self.title = @"早起的太阳";

self.navigationController.navigationBar.barTintColor = [UIColor brownColor];

self.navigationController.navigationBar.titleTextAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:25],NSForegroundColorAttributeName:[UIColor whiteColor]};

self.view.backgroundColor = [UIColor whiteColor];
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
view.center = self.view.center;
view.backgroundColor = [UIColor redColor];
[self.view addSubview:view];

/**
 *  使一张图片具有阴影的效果
 */
//1.Opacity :不透明度(不透明度只要大于1就说明是有阴影的)
view.layer.shadowOpacity = 1;
//2.阴影的偏移 CGSizeMake(X[正的右偏移,负的左偏移], Y[正的下偏移,负的上偏移]);
//view.layer.shadowOffset = CGSizeMake(10, -10);
//3.设置阴影部分的面积颜色
view.layer.shadowColor = [UIColor yellowColor].CGColor;
//4.阴影的圆角
view.layer.shadowRadius = 20;
//5.view的圆角
view.layer.cornerRadius = 50;
//6.view的边宽
view.layer.borderWidth = 1;
//7.view的边颜色
view.layer.borderColor = [UIColor whiteColor].CGColor;    
}

(3)CALayer的图形旋转与缩放:都以layer图层操作为例(下面以一个button为例)

缩放与旋转

主要阐述两点:旋转和缩放两种方法

X,Y,Z
  • <1>旋转(这两种方式一样)(建议不要使用KVC快速缩放或者旋转)

    1.旋转
    //button.layer.transform = CATransform3DMakeRotation(M_PI, 1, 0.5, 1);
    2.旋转
    [button.layer setValue:@M_PI forKeyPath:@"transform.rotation"];

  • <2>缩放(两种方式一样)

    1.快速进行图层缩放

      //button.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1);
    

    2.缩放
    [button.layer setValue:@0.5 forKeyPath:@"transform.scale"];

上面的内容代码 密码: 7u95

二.自己创建的CALayer层

自己创建图层

1.创建图层

CALayer *layer = [CALayer layer];

layer.frame = CGRectMake(WIDTH/2-100, 200, 200, 200);

layer.backgroundColor = [UIColor brownColor].CGColor;

2.图层只能添加到图层上面

 [self.view.layer addSublayer:layer];

3.给图层添加图片

 layer.contents = (id)([UIImage imageNamed:@"girl.jpg"].CGImage);

问题:为什么CALayer图层的颜色后面要加.CGColor而图片加.CGImage

解释如下:

首先:

 (1) CALayer 是定义在QuartzCore框架中的
 (2) CGImageRef , CGColorRef  两种数据类型是定义在CoreGraphics中的
 (3) UIColor , UIImage 是定义在UIKit 框架中

其次:

 (1) QuartzCore框架和CoreGraphics 框架是可以跨平台使用的,在iOS和Mac OS X 上都能使用
 (2) 但是UIKit 只能在iOS中使用

所以:为了保证可移植性,QuartzCore不能使用UIImage,UIColor,只能使用CGImageRef ,CGColorRef

三.UIView与CALayer的选择

CALayer继承于NSObject
UIView继承于UIResponder(具有响应事件的能力)
  • (1) 通过CALayer,就能做出跟UIImageView 一样的界面效果

  • (2) 既然CALayerUIView 都能实现相同的显示效果,那如何选择???

    解释: 对比CALayer ,UIView 多了一个事件处理的功能,也就是说,CALayer 不能处理用户的触摸事件,而UIView可以,所以:如果显示出来的东西需要跟用户进行交互的话,用UIView:如果不需要跟用户进行交互的话,就用UIVIew或者CALayer都可以,当然,CALayer 的性能会高一些,因为它多了处理事件的功能,更加轻量级.

**四.介绍一下CALayer的两个重要属性position 和 anchorPoint **

  • @property CGPoint position; 用来设置CALayer 在父层中的位置,以父层的左上角为原点(0,0):类似frame

  • @property CGPoint anchorPoint; 称为"定位点","锚点",决定着CALayer 身上的哪个点会在position 属性所指的位置,以自己的左上角为原点(0,0),它的x,y取值范围都是0~1,默认值为(0.5,0.5):类似bounds

只有图层才有anchorPoint这个属性

anchorPoint锚点介绍

具体的显示(锚点默认在中心=center) 在旋转时:锚点也就是旋转的点

具体的显示

五.隐式动画(手动创建的CALayer才有隐式动画):也就是说自带动画,不需要加animation

  • 每一个UIView内部都默认连着一个CALayer,我们可用称这个LayerRootLayer(根层)

  • 所有的非Root Layer,也就是手动创建的CALayer对象,都存在隐式动画

下面以一个clayer的旋转为例
旋转一般会用到 角度转弧度: 角度/180.0*M_PI

宏定义: #define angle2radion(angle)  ((angle) / 180.0 * M_PI)

重点提一下:旋转的中心: layer.anchorPoint = CGPointZero;

anchorPoint的范围是(0~1,0~1);

隐式动画

隐式动画代码 密码: icgj
切记:非根层才能建立隐式动画(也就是自定义的CALayer)

六.时钟的制作

晓效果图如下:

时钟的制作

在涉及到旋转的时候我们首先要确定的是它的锚点,其次是position

这里主要是运用了1.隐式动画.2.角度转弧度.3.再就是一些旋转的设置

 角度转弧度
 #define angle2radion(angle)  ((angle) / 180.0 * M_PI)

时钟的代码:里面有中详细的注释 密码: b2c8

在此多数几句:如何获取系统的时间

//获取当前的系统时间
//获取当前日历对象
NSCalendar  *calendar =[NSCalendar currentCalendar];
//获取日期的组件,年月日,时分秒
//components: 需要获取日期组件
//formDate:获取哪个日期组件
//经验:以后枚举中有移位运算符(<<),一般来说我们就可以用 |  :"并" 的方式
NSDateComponents  *dateComponents = [calendar components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];

NSLog(@"小时==%ld",dateComponents.hour);
NSLog(@"分钟==%ld",dateComponents.minute);
NSLog(@"秒==%ld",dateComponents.second);

七.核心动画(介绍四个,CABasicAnimation, CAKeyframeAnimation, CATransition, CAAnimationGroup)

  • <1>.Core Animation 中文翻译为核心动画,它是一组非常强大的动画处理API,使用它可以做出非常炫酷的效果,而且往往是事半功倍,也就是说,使用少量的代码就可以实现非常强大的功能.

  • <2>.Core Animation 可以使用在Mac OS XiOS平台.

  • <3>.Core Animation 的动画执行过程都是在后台操作的,不会阻塞主线程.

  • <4>.需要注意的是:Core Animation 是直接作用在CALayer上的,并非UIView.在此也说一下UIView也有动画,其实也是在底层封装了核心动画

核心动画的结构
  • (1)CABasicAnimation创建动画(这里仅仅以一个view的移动为例):只能用于2个值之间
CABasicAnimation创建动画.gif
  /**
   *  CABasicAnimation创建核心动画
   */
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

    //创建动画
    CABasicAnimation *animation = [CABasicAnimation animation];

    //描述下修改那个属性产生动画
    animation.keyPath = @"position";

    //设置值(点转化为对象)
    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(arc4random_uniform(500), arc4random_uniform(500))];

    //取消动画反弹需要2步
    //1.设置动画完成时候不要移除动画
    animation.removedOnCompletion = NO;
    //2.设置动画执行完成保持最新的效果
    animation.fillMode = kCAFillModeForwards;

    //添加动画
    [_redView.layer addAnimation:animation forKey:nil];

}

如果先个缩放就把上面的值改了就好

 animation.keyPath = @"transform.scale";
 animation.toValue = @0.5;

如果想做一个心脏的话那么久设置一个一直执行动画,也可以调节动画的时间长短,下面的代码放到一个方法里面就好(可以做心脏的跳动)
二维的放大和缩小
_redVie就是一个UIImageView的类的对象

跳动的心脏
//创建动画
CABasicAnimation *animation = [CABasicAnimation animation];

//描述下修改那个属性产生动画
animation.keyPath = @"transform.scale";

//设置值
animation.toValue = @0.5;

//设置每次动画的时间
animation.duration = 1;

//如果想一直执行动画,很久
animation.repeatCount = MAXFLOAT;//表示最大次数

//取消动画反弹需要2步
//1.设置动画完成时候不要移除动画
animation.removedOnCompletion = NO;
//2.设置动画执行完成保持最新的效果
animation.fillMode = kCAFillModeForwards;

//添加动画
[_redView.layer addAnimation:animation forKey:nil];

当然我们还可以设置旋转

旋转的心脏
  animation.keyPath = @"transform.rotation";
  animation.toValue = @(M_PI*2);//360旋转
  • (2).cakeyframeanimation创建帧动画

1.心脏的抖动


心脏的抖动

代码如下:

//创建动画
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
//根据路径来走
animation.keyPath = @"transform.rotation";
//角度的设定
animation.values = @[@angle2radion(-5),@angle2radion(5),@angle2radion(-5)];
//不停地循环来抖动
animation.repeatCount = MAXFLOAT;
//添加在图层上的动画
[_heart.layer addAnimation:animation forKey:nil];

当然你也可以设置它的锚点

_heart.layer.anchorPoint = CGPointZero;(以心脏的左上为旋转的点来抖动)

2.让心脏绕着指定轨迹来做运动(用到了贝塞尔曲线):改变的是位置position

心脏的转圈

核心代码如下:

//创建动画
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
//改变的位置
animation.keyPath = @"position";
//动画执行的时间
animation.duration = 2;
//设定转圈的路径
animation.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(100, 200, 200, 200)].CGPath;
//重复动画
animation.repeatCount = MAXFLOAT;
//添加动画
[_heart.layer addAnimation:animation forKey:nil];

3.心脏根据画出路径来走

首先要建立一个UIView 也就是图层(画画的地方)

效果如下

心脏根据路径来旋转

心脏根据路径走的代码 密码: dq43

核心代码如下:

@property(nonatomic,strong) UIBezierPath *path;

/**
 *  手指接触屏幕的点
 */
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//touch
UITouch *touch = [touches anyObject];
//获取手指的触摸点
CGPoint pointCurrent = [touch locationInView:self];
//创建路径
UIBezierPath *path = [UIBezierPath bezierPath];

//记录路径
_path = path;

//设置起点
[path moveToPoint:pointCurrent];

}

/**
 *  手指一动的时候的点
 */
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//touch
UITouch *touch = [touches anyObject];
//获取手指的触摸点
CGPoint pointCurrent = [touch locationInView:self];

//保存每一个路径
[_path addLineToPoint:pointCurrent];

//每次一动就调用画画
[self setNeedsDisplay];

}

/**
 *  画线
 */
-(void)drawRect:(CGRect)rect
{
   [_path stroke];
}

/**
 *  手指抬起来的时候
 */
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

//创建动画
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];

animation.keyPath = @"position";

animation.duration = 2;

animation.path = _path.CGPath;

animation.repeatCount = MAXFLOAT;

//添加动画
[[[self.subviews firstObject] layer] addAnimation:animation forKey:nil];

 }
添加的动画

添加动画

[[[self.subviews firstObject] layer] addAnimation:animation forKey:nil];

注意:我再重复一次,动画式添加在图层上的

  • (3).转场动画CATransition

转场动画转场代码要写在一起:(切记)

效果图如下:

转场动画

核心代码如下:(转场动画和转场代码要写在一起)

 /**
  *  在触摸时的变化
  */
 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    转场代码
    if(i==4)
    {
         i = 1;
    }
    NSString *imageName = [NSString stringWithFormat:@"%d.jpg",i];
    _imageView.image = [UIImage imageNamed:imageName];
    i++;

   添加转场动画
   CATransition *animation = [CATransition animation];
   animation.type = @"cube";
   animation.duration = 2;
   [_imageView.layer addAnimation:animation forKey:nil];
}

如果想看其他的效果:可以更改下面的值:

 animation.type = @"cube";
转场过渡效果

转场动画代码 密码: ffmy

  • (4).动画组(之前的动画只能缩放或者旋转,动画组可以实现旋转和缩放同时进行)

效果如下:

动画组

核心的代码如下:(也就是一个group来包含很多的动画组合起来的)

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
 //同时缩放,平移,旋转

 CAAnimationGroup *group = [CAAnimationGroup animation];

 group.duration = 2;

 CABasicAnimation *scale = [CABasicAnimation animation];
 scale.keyPath = @"transform.scale";
 scale.toValue = @0.5;

 CABasicAnimation *rotation = [CABasicAnimation animation];
 rotation.keyPath = @"transform.rotation";
 rotation.toValue = @(arc4random_uniform(M_PI));

 CABasicAnimation *position = [CABasicAnimation animation];
 position.keyPath = @"position";
 position.toValue = [NSValue valueWithCGPoint:CGPointMake(arc4random_uniform(200)+100, arc4random_uniform(400)+100)];

 group.animations = @[scale,rotation,position];

 //取消动画反弹需要2步
 //1.设置动画完成时候不要移除动画
 group.removedOnCompletion = NO;
 //2.设置动画执行完成保持最新的效果
 group.fillMode = kCAFillModeForwards;

 [_imageView.layer addAnimation:group forKey:nil];

}

动画组代码 密码: 4yiq

再重复一次:核心动画式加在图层上的

八.UIView与核心动画的区别

注意:
1.核心动画一切都是假象,并不会真实的改变图层的属性值.如果以后做动画的时候,不需要与用户交互,通常用核心动画(转场)

原因:当我们改变一个视图的position的时候,它的position并没有发生改变,大家可以打印一下看看(打印看看)

NSLog(@"%@",NSStringFromCGPoint(_girl.layer.position));

2.UIView动画必须通过修改属性的真实值,才有动画效果

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

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,471评论 6 30
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,101评论 5 13
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,082评论 1 23
  • Core Animation Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,...
    45b645c5912e阅读 3,016评论 0 21
  • Core Animation其实是一个令人误解的命名。你可能认为它只是用来做动画的,但实际上它是从一个叫做Laye...
    小猫仔阅读 3,689评论 1 4