浅汇-iOS 动画

        在iOS开发中,制作动画效果是最让开发者享受的环节之一。一个设计严谨、精细的动画效果能给用户耳目一新的效果,吸引他们的眼光 —— 这对于app而言是非常重要的。我们总是追求更为酷炫的实现,如果足够仔细,我们不难发现一个好的动画通过步骤分解后本质上不过是一个个简单的动画实现。本文就个人搜集的一些动画相关的理论和实践知识做个小结,不足之处请勿见怪。


理论

      UIView只是CALyer之上的封装,更准确的来说,UIView是CALyer的简版封装,加上事件处理的集合类。CALayer是QuartzCore库内的类,是iOS上最基本的绘制单元。其次,我们知道iOS平台的Cocoa Touch 是源于OS X平台的Cocoa),是在Cocoa的基础上添加了适用于移动手机设备的手势识别、动画等特性;但从底层实现上来说,Cocoa Touch与Cocoa共用一套底层的库,其中就包括了QuartCore.framework;但QuartCore.framework一开始就是为OS X设计的,所以其中有部分特性是不适合做移动设备开发的,比如最重要的坐标系统。因此,我们也就不难理解为何UIView/NSView在CALayer上做了一层封装。

基于UIView实现的动画

简单的Block动画

[UIView animateWithDuration:0.2 animations:^{  }];

[UIView animateWithDuration:0.5f animations:^{  } completion:^(BOOL finished) { //    }];

UIView [begin commit]

_demoView.frame = CGRectMake(0, SCREEN_HEIGHT/2-50, 50, 50);

[UIView beginAnimations:nil context:nil];

[UIView setAnimationDuration:1.0f];

_demoView.frame = CGRectMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50, 50, 50);

[UIView commitAnimations];

  弹性动画

[UIView animateWithDuration:0.8 delay:0  usingSpringWithDamping:0.5 initialSpringVelocity:6  options:UIViewAnimationOptionCurveEaseOut animations:^{  //

} completion:^(BOOL finished) {  }];    //参数:持续时间,延迟时间,阻尼系数,初始速度

关键帧动画(中间可以添加合适多的帧来做不同的衔接动画)

UIView animateKeyframesWithDuration:3.f

delay:0.0

options:UIViewKeyframeAnimationOptionCalculationModeLinear

animations:^{

[UIView addKeyframeWithRelativeStartTime:0.0

relativeDuration:0.8

animations:^{

//

}];

[UIView addKeyframeWithRelativeStartTime:0.8

relativeDuration:1.6

animations:^{

//

}];                                                              }

completion:^(BOOL finished) {

//                              }];

CALayer动画



值得注意的是  CASpringAnimation 是 CABasicAnimation 的子类用于实现弹性动画的效果。

常用属性

duration : 动画的持续时间

beginTime : 动画的开始时间

repeatCount : 动画的重复次数

autoreverses : 执行的动画按照原动画返回执行

timingFunction : 控制动画的显示节奏系统提供五种值选择,

分别是:

kCAMediaTimingFunctionLinear 线性动画

kCAMediaTimingFunctionEaseIn 先慢后快(慢进快出)

path:关键帧动画中的执行路径

type : 过渡动画的动画类型,系统提供了四种过渡动画。

kCATransitionFade 渐变效果

kCATransitionMoveIn 进入覆盖效果

subtype : 过渡动画的动画方向

kCATransitionFromRight 从右侧进入

kCATransitionFromLeft 从左侧进入

基础动画主要提供了对于CALayer对象中的可变属性进行简单动画的操作。比如:位移、透明度、缩放、旋转、背景色等等。

重要属性

fromValue : keyPath对应的初始值

toValue : keyPath对应的结束值

基础动画(CABaseAnimation)

0:1  1:0  实现下拉剪头的展开和收起

CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

rotationAnimation.duration = 0.3f;

rotationAnimation.repeatCount = 1;

rotationAnimation.autoreverses = NO;

rotationAnimation.fromValue = [NSNumber numberWithFloat: beginValue*M_PI];

rotationAnimation.toValue = [NSNumber numberWithFloat:endValue*M_PI];

rotationAnimation.removedOnCompletion = NO;

rotationAnimation.fillMode = kCAFillModeForwards;

rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

[pinLayer addAnimation:rotationAnimation forKey:@"revItUpAnimation"];

关键帧动画(CAKeyframeAnimation

CAKeyframeAnimation和CABaseAnimation都属于CAPropertyAnimatin的子类。`CABaseAnimation只能从一个数值(fromValue)变换成另一个数值(toValue),而CAKeyframeAnimation则会使用一个NSArray保存一组关键帧。 `

重要属性

values : 就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧

path : 可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略。

keyTimes : 可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的。

组合动画:

CAKeyframeAnimation *anima1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];

NSValue *value0 = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-50)];

NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2-50)];

NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2+50)];

NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2+50)];

NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2-50)];

NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50)];

anima1.values = [NSArray arrayWithObjects:value0,value1,value2,value3,value4,value5, nil];

//缩放动画

CABasicAnimation *anima2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

anima2.fromValue = [NSNumber numberWithFloat:0.8f];

anima2.toValue = [NSNumber numberWithFloat:2.0f];

//旋转动画

CABasicAnimation *anima3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];

anima3.toValue = [NSNumber numberWithFloat:M_PI*4];

//组动画

CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];

groupAnimation.animations = [NSArray arrayWithObjects:anima1,anima2,anima3, nil];

groupAnimation.duration = 4.0f;

[_demoView.layer addAnimation:groupAnimation forKey:@"groupAnimation"];

过渡动画(CATransition) 多数为私有的API使用后`无法上架app`。

私有API提供了其他很多非常炫的过渡动画,比如@”cube”、@”suckEffect”、@”oglFlip”、 @”rippleEffect”、@”pageCurl”、@”pageUnCurl”、@”cameraIrisHollowOpen”、@”cameraIrisHollowClose”等。

粒子动画

transform动画

transform是一个非常重要的属性,它在矩阵变换的层面上改变视图的显示效果,完成旋转、形变、平移等等操作。在它被修改的同时,视图的frame也会被真实改变。有两个数据类型用来表示transform,分别是CGAffineTransform和CATransform3D。前者作用于UIView,后者为layer层次的变换类型。基于后者可以实现更加强大的功能。

对于想要了解矩阵变换是如何作用实现的,可以参考这篇博客:CGAffineTransform 放射变换

在开始使用transform实现你的动画之前,我先介绍几个常用的函数:

/// 用来连接两个变换效果并返回。返回的t = t1 * t2

CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2)

/// 矩阵初始值。[ 1 0 0 1 0 0 ]

CGAffineTransformIdentity

/// 自定义矩阵变换,需要掌握矩阵变换的知识才知道怎么用。参照上面推荐的原理链接

CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)

/// 旋转视图。传入参数为 角度 * (M_PI / 180)。等同于 CGAffineTransformRotate(self.transform, angle)

CGAffineTransformMakeRotation(CGFloat angle)

CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)

/// 缩放视图。等同于CGAffineTransformScale(self.transform, sx, sy)

CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)

CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)

/// 缩放视图。等同于CGAffineTransformTranslate(self.transform, tx, ty)

CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)

CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)

特殊地,transform属性默认值为CGAffineTransformIdentity,可以在形变之后设置该值以还原到最初状态

样例self.demoImageView.transform = CGAffineTransformIdentity;

transform严格的说不是一种动画,而是动画中的一部分操作,我拿出来说是因为它同时出现在了UIView 动画和CALayer动画中。

一些应用

- 利用上面CALayer 基础动画的代码实现下拉剪头的展开和收起,还可以实现时钟指针的旋转

  pinLayer = [CALayer layer];

[pinLayer setBounds:CGRectMake(0, 0, 14, 8)];

[pinLayer setContents:(id)[UIImage imageNamed:@"downArrow.png"].CGImage];

[pinLayer setPosition:CGPointMake(305*NEWX,20)];

[pinLayer setAnchorPoint:CGPointMake(0.5, 0.5)];

[behindBgView.layer addSublayer:pinLayer];

输入框在输入错误信息时的摇晃效果

利用CAShapeLayer 和CABasicAnimation 可以实现加载动画


iOS渲染视图的层级图


- UIKit:最常用的视图框架,封装度最高,都是OC对象

- CoreAnimation:提供强大的2D和3D动画效果

- CoreGraphics:主要绘图系统,常用于绘制自定义视图,纯C的API,使用Quartz2D做引擎

- CoreImage:给图片提供各种滤镜处理,比如高斯模糊、锐化等

- OpenGL-ES:主要用于游戏绘制,但它是一套编程规范,具体由设备制造商实现


更多内容可以点击(iOS开发UI篇---iOS Core Animation 总结)


小结

事实告诉我们动画是要靠设计的,你看我上面的动画抽的一笔,但事实上用同样的代码可以写出很漂亮的动画。

一篇很棒的动画总结文章

iOS 图像渲染过程解析

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

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,461评论 6 30
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,076评论 1 23
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,091评论 5 13
  • 显式动画 显式动画,它能够对一些属性做指定的自定义动画,或者创建非线性动画,比如沿着任意一条曲线移动。 属性动画 ...
    清风沐沐阅读 1,916评论 1 5
  • 一、简介iOS 动画主要是指Core Animation框架。官方使用文档地址为:Core Animation G...
    LZM轮回阅读 1,886评论 1 14