iOS开发超神学院iOS精华文章iOS 开发每天分享优质文章

核心动画详细阐述

2016-10-23  本文已影响221人  IIronMan

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

(2).CALayer的基本使用

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

阴影的展示

简单的代码展示

- (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

上面的内容代码 密码: 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(具有响应事件的能力)

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

只有图层才有anchorPoint这个属性

anchorPoint锚点介绍

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

具体的显示

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

下面以一个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)

核心动画的结构 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旋转

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];

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

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

效果图如下:

转场动画

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

 /**
  *  在触摸时的变化
  */
 -(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

效果如下:

动画组

核心的代码如下:(也就是一个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) {
    
    
}];
上一篇下一篇

猜你喜欢

热点阅读