iOS 动画

一、CALayer

  • CALayer很多属性在修改时都能形成动画效果(不需要借助动画类),这种属性称为“隐式动画属性”。但是对于UIView的根图层而言属性的修改并不形成动画效果,因为很多情况下根图层更多的充当容器的做用,如果它的属性变动形成动画效果会直接影响子图层。

  • CALayer的属性中,如果一个被标记为Animatable,那么它具有以下两个特点:

    1、直接对它赋值可能产生隐式动画;
    2、我们的CAAnimation的keyPath可以设置为这个属性的名字。

  • 可实现动画的属性:

    坐标尺寸:bounds、frame(不支持隐私动画)、center
    视图显示:backgroundColor、alpha、hidden
    形态变化:transform

  • 隐式属性动画的本质是这些属性的变动默认隐含了CABasicAnimation动画实现,详情大家可以参照Xcode帮助文档中“Animatable Properties”一节。

  • 在CALayer中很少使用frame属性,因为frame本身不支持动画效果,通常使用bounds和position代替。

  • CALayer中透明度使用opacity表示而不是alpha;中心点使用position表示而不是center。

  • anchorPoint属性是图层的锚点,范围在(01,01)表示在x、y轴的比例,这个点永远可以同position(中心点)重合,当图层中心点固定后,调整anchorPoint即可达到调整图层显示位置的作用(因为它永远和position重合)

一、 CoreAnimation

在iOS中核心动画分为几类:基础动画、关键帧动画、动画组、转场动画。各个类的关系大致如下:


image.png
  • 基础动画CABasicAnimation

    • 步骤:1.初始化动画并设置动画属性 2.设置动画属性初始值(可以省略)、结束值以及其他动画属性 3.给图层添加动画
    • 以SVProgress为例,起主要动画代码如下:
-(void) SVProgressRing {
    CGPoint arcCenter = CGPointMake(200, 300);
    UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:30 startAngle:(CGFloat)-M_PI_2 endAngle:(CGFloat) (M_PI + M_PI_2) clockwise:YES];
    
    CAShapeLayer *ringAnimatedLayer = [CAShapeLayer layer];
    ringAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale];
    ringAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2);
    ringAnimatedLayer.fillColor = [UIColor clearColor].CGColor;
    ringAnimatedLayer.strokeColor = [UIColor greenColor].CGColor;
    ringAnimatedLayer.lineWidth = 4;
    ringAnimatedLayer.lineCap = kCALineCapRound;
    ringAnimatedLayer.lineJoin = kCALineJoinBevel;
    ringAnimatedLayer.path = smoothedPath.CGPath;
    ringAnimatedLayer.strokeStart = 0;
    ringAnimatedLayer.strokeEnd = 0.6;
    
    CAShapeLayer *backgroundLayer = [CAShapeLayer layer];
    backgroundLayer.fillColor = [UIColor clearColor].CGColor;
    backgroundLayer.strokeColor = [[UIColor greenColor] colorWithAlphaComponent:0.1].CGColor;
    backgroundLayer.lineWidth = 4;
    backgroundLayer.path = smoothedPath.CGPath;
    backgroundLayer.strokeStart = 0;
    backgroundLayer.strokeEnd = 1;
    
    
    [self.view.layer addSublayer:backgroundLayer];
    [self.view.layer addSublayer:ringAnimatedLayer];
    
    // 0.015 到 0.515 是一个圆 从0.015 擦除到 0.515,从0.515到1依然是实线
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.fromValue = @0.0;
    animation.toValue = @1;
    animation.duration = 3;
    animation.repeatCount = INFINITY;
    animation.removedOnCompletion = NO;
//    animation.timingFunction = LINEF
    
    [ringAnimatedLayer addAnimation:animation forKey:@"progress"];
}
  • 动画组

  • 关键帧动画CAKeyframeAnimation

  • 转场动画CATransition

  • CASpringAnimation

  • 逐帧动画

    • 虽然在核心动画没有直接提供逐帧动画类型,但是却提供了用于完成逐帧动画的相关对象CADisplayLink。CADisplayLink是一个计时器,但是同NSTimer不同的是,CADisplayLink的刷新周期同屏幕完全一致。例如在iOS中屏幕刷新周期是60次/秒,CADisplayLink刷新周期同屏幕刷新一致也是60次/秒,这样一来使用它完成的逐帧动画(又称为“时钟动画”)完全感觉不到动画的停滞情况。

二、UIView 封装的方法

  • 非block

    • UIView本身对于基本动画和关键帧动画、转场动画都有相应的封装,在对动画细节没有特殊要求的情况下使用起来也要简单的多。
      执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码放在[UIView beginAnimations:nil context:nil]和[UIView commitAnimations]之间
    • 相关动画函数 及 代码示例
      • (void)setAnimationDelegate:(id)delegate 设置动画代理对象,当动画开始或者结束时会发消息给代理对象
      • (void)setAnimationWillStartSelector:(SEL)selector 当动画即将开始时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector
      • (void)setAnimationDidStopSelector:(SEL)selector 当动画结束时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector
      • (void)setAnimationDuration:(NSTimeInterval)duration 动画的持续时间,秒为单位
      • (void)setAnimationDelay:(NSTimeInterval)delay 动画延迟delay秒后再开始
      • (void)setAnimationStartDate:(NSDate *)startDate 动画的开始时间,默认为now
      • (void)setAnimationCurve:(UIViewAnimationCurve)curve 动画的节奏控制
      • (void)setAnimationRepeatCount:(float)repeatCount 动画的重复次数
      • (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses 如果设置为YES,代表动画每次重复执行的效果会跟上一次相反
      • (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache 设置视图view的过渡效果, transition指定过渡类型, cache设置YES代表使用视图缓存,性能较好
- (void) animate {
    //首尾式动画
     [UIView beginAnimations:nil context:nil];
     //执行动画
     //设置动画执行时间
    [UIView setAnimationDuration:2.0];
     //设置代理
     [UIView setAnimationDelegate:self];
     //设置动画执行完毕调用的事件
     [UIView setAnimationDidStopSelector:@selector(didStopAnimation)];
     self.customView.center=CGPointMake(200, 300);
     [UIView commitAnimations];
}
  • block方式

[UIView animateWithDuration: delay: options: animations: completion:^(BOOL finished) {}]

以上方法中的options一项需要传入一个枚举,这个枚举大概控制的是这几个要素:当前动画嵌套中的动画执行随时间的快慢种类(先快后慢等..)。动画要一直重复吗。如果我使用转场动画那么我用哪种转场效果。还有子动画嵌套在父动画中时我们如何对待父动画中的相同选项等等

  • UIViewAnimationOptions(可以同时选择多个进行设置):

    UIViewAnimationOptionLayoutSubviews:动画过程中保证子视图跟随运动。提交动画的时候布局子控件,表示子控件将和父控件一同动画。
    UIViewAnimationOptionAllowUserInteraction:动画过程中允许用户交互。
    UIViewAnimationOptionBeginFromCurrentState:所有视图从当前状态开始运行。
    UIViewAnimationOptionRepeat:重复运行动画。
    UIViewAnimationOptionAutoreverse :动画运行到结束点后仍然以动画方式回到初始点。执行动画回路,前提是设置动画无限重复
    UIViewAnimationOptionOverrideInheritedDuration:忽略嵌套动画时间设置。忽略外层动画嵌套的时间变化曲线
    UIViewAnimationOptionOverrideInheritedCurve:忽略嵌套动画速度设置。通过改变属性和重绘实现动画效果,如果key没有提交动画将使用快照
    UIViewAnimationOptionAllowAnimatedContent:动画过程中重绘视图(注意仅仅适用于转场动画)。
    UIViewAnimationOptionShowHideTransitionViews:视图切换时直接隐藏旧视图、显示新视图,而不是将旧视图从父视图移除(仅仅适用于转场动画)用显隐的方式替代添加移除图层的动画效果
    UIViewAnimationOptionOverrideInheritedOptions :不继承父动画设置或动画类型。忽略嵌套继承的选项
    ----------------------------------------------------------------------------
    2.动画速度控制(可从其中选择一个设置)时间函数曲线相关时间曲线函数
    UIViewAnimationOptionCurveEaseInOut:动画先缓慢,然后逐渐加速。
    UIViewAnimationOptionCurveEaseIn :动画逐渐变慢。
    UIViewAnimationOptionCurveEaseOut:动画逐渐加速。
    UIViewAnimationOptionCurveLinear :动画匀速执行,默认值。
    -----------------------------------------------------------------------------
    3.转场类型(仅适用于转场动画设置,可以从中选择一个进行设置,基本动画、关键帧动画不需要设置)转场动画相关的
    UIViewAnimationOptionTransitionNone:没有转场动画效果。
    UIViewAnimationOptionTransitionFlipFromLeft :从左侧翻转效果。
    UIViewAnimationOptionTransitionFlipFromRight:从右侧翻转效果。
    UIViewAnimationOptionTransitionCurlUp:向后翻页的动画过渡效果。
    UIViewAnimationOptionTransitionCurlDown :向前翻页的动画过渡效果。
    UIViewAnimationOptionTransitionCrossDissolve:旧视图溶解消失显示下一个新视图的效果。
    UIViewAnimationOptionTransitionFlipFromTop :从上方翻转效果。
    UIViewAnimationOptionTransitionFlipFromBottom:从底部翻转效果。

三 UIView封装的动画与CALayer动画的对比

UIView封装的动画执行完毕之后不会反弹。即如果是通过CALayer核心动画改变layer的位置状态,表面上看虽然已经改变了,但是实际上它的位置是没有改变的(可使用动画代理防止动画回弹)。使用UIView和CALayer都能实现动画效果,但是在真实的开发中,一般还是主要使用UIView封装的动画,而很少使用CALayer的动画。

四、参考文章

iOS开发系列--让你的应用“动”起来

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

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,438评论 6 30
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,069评论 1 23
  • 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你...
    Yiart阅读 3,784评论 3 34
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,083评论 5 13
  • iOS核心动画-Core Animation 概论 目标:1. 学会使用图层精简非交互式绘图;2. 通过核心动画创...
    ValienZh阅读 1,879评论 2 9