iOS开发-CoreAnimation

CALayer

CALayer是个与UIView很类似的概念,同样有layer,sublayer...,同样有backgroundColor、frame等相似的属性,我们可以将UIView看做一种特殊的CALayer,只不过UIView可以响应事件而已。一般来说,layer可以有两种用途,二者不互相冲突:一是对view相关属性的设置,包括圆角、阴影、边框等参数,更详细的参数请点击这里;二是实现对view的动画操控。因此对一个view进行core animation动画,本质上是对该view的.layer进行动画操纵。

CAAnimation

CAAnimation可分为四种:

1. CABasicAnimation 基本动画

通过设定起始点,终点,时间,动画会沿着你这设定点进行移动。可以看做特殊的CAKeyFrameAnimation
创建cabaseanimation 的方法,但是在最新的apple开发文档没有查到path到底有哪些,网上搜罗了一下,并猜测path跟layer中的属性字段是一致的如background

/\*\* Subclass for property-based animations. \*\*/
@interface CAPropertyAnimation : CAAnimation
/\* Creates a new animation object with its `keyPath' property set to \* 'path'. \*/
+ (instancetype)animationWithKeyPath:(nullable NSString *)path;
/\* The key-path describing the property to be animated. \*/
@property(nullable, copy) NSString *keyPath;

path用途
rotaion.x旋转,弧度,X轴
rotaion.y旋转,弧度,Y轴
rotaion.z旋转,弧度,Z轴
rotaion旋转,弧度,Z轴,完全等同于rotation.z
scale.x缩放,X轴
scale.y缩放,Y轴
scale.z缩放,Z轴
scale缩放,XYZ轴
translation.x移动,X轴
translation.y移动,Y轴
translation.z移动,Z轴
translation移动,XY轴,value值为NSSize或者CGSize类型
opacity等zPosition、frame、backgroundColor、cornerRadius类似的layer中的各种属性

所以有如下代码

​​​​/\*\* \* 透明度动画 \*/
-(void)opacityAniamtion{
    CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"opacity"];
    anima.fromValue = [NSNumber numberWithFloat:1.0f];
    anima.toValue = [NSNumber numberWithFloat:0.2f];
    anima.duration = 1.0f;
    [_demoView.layer addAnimation:anima forKey:@"opacityAniamtion"];
}
/\*\* \* 缩放动画 \*/
-(void)scaleAnimation{ 
    CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"transform.scale"];//同上
    anima.toValue = [NSNumber numberWithFloat:2.0f];
    anima.duration = 1.0f;
    [_demoView.layer addAnimation:anima forKey:@"scaleAnimation"]; 
}

/\*\* \* 旋转动画 \*/
-(void)rotateAnimation{
    CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];//绕着z轴为矢量,进行旋转(@"transform.rotation.z"==@@"transform.rotation")
    anima.toValue = [NSNumber numberWithFloat:3*M_PI];
    anima.duration = 1.0f;
    [_demoView.layer addAnimation:anima forKey:@"rotateAnimation"];
}
/\*\* \* 背景色变化动画 \*/
-(void)backgroundAnimation{
    CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    anima.toValue =(id) [UIColor greenColor].CGColor;
    anima.duration = 1.0f;
    [_demoView.layer addAnimation:anima forKey:@"backgroundAnimation"];
}

有人会疑惑addanimation:forkey: 这个key到底是什么官方的注释是

/\*\* Animation methods. \*\*/

/\* Attach an animation object to the layer. Typically this is implicitly \* invoked through an action that is an CAAnimation object. \* \* 'key' may be any string such that only one animation per unique key \* is added per layer. The special key 'transition' is automatically \* used for transition animations. The nil pointer is also a valid key. \* \* If the `duration' property of the animation is zero or negative it \* is given the default duration, either the value of the \* `animationDuration' transaction property or .25 seconds otherwise. \* \* The animation is copied before being added to the layer, so any \* subsequent modifications to `anim' will have no affect unless it is \* added to another layer. \*/

翻译下

/ \* \*动画方法。\* \* // 
\* 将动画对象附加到层。通常这是隐式地
\* 通过一个动作是一个CAAnimation对象调用。
\* “key”可以是任何字符串,这样每个唯一键只有一个动画
\* 添加每层。特殊键自动“过渡”
\* 用于过渡动画。空指针也是一个有效的关键。
\* 如果动画的“持续时间”属性是零或消极
\* 默认时间,给出的值
\* animationDuration事务属性或。25秒。
\* 动画复制之前添加到层,所以任何后续修改“动画”没有影响,除非它是添加到另一层

所以大家放心使用CABasicAnimation!

2. CAKeyframeAnimation 关键帧动画

Keyframe顾名思义就是关键点的frame,你可以通过设定CALayer的始点、中间关键点、终点的frame,时间,动画会沿你设定的轨迹进行移动 CAKeyframeAnimation 的一些比较重要的属性

2.1. path
这是一个 CGPathRef 对象,默认是空的,当我们创建好CAKeyframeAnimation的实例的时候,可以通过制定一个自己定义的path来让某一个物体按照这个路径进行动画。这个值默认是nil,当其被设定的时候values 这个属性就被覆盖。

2.2. values

一个数组,提供了一组关键帧的值,当使用path的 时候 values的值自动被忽略。

下面是一个简单的例子 效果为动画的连续移动一个block到不同的位置

/\*\* \* 关键帧动画 values \*/
-(void)keyFrameAnimation{
    CAKeyframeAnimation *anima = [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)];
    anima.values = [NSArray arrayWithObjects:value0,value1,value2,value3,value4,value5, nil];
    anima.duration = 2.0f;
    anima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];//设置动画的节奏
    anima.delegate = self;//设置代理,可以检测动画的开始和结束
    [_demoView.layer addAnimation:anima forKey:@"keyFrameAnimation"];
}

/\*\* \* path动画 \*/
-(void)pathAnimation{
    CAKeyframeAnimation *anima = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(SCREEN_WIDTH/2-100, SCREEN_HEIGHT/2-100, 200, 200)];
    anima.path = path.CGPath;
    anima.duration = 2.0f;
    [_demoView.layer addAnimation:anima forKey:@"pathAnimation"];
}

对比UIView动画跟关键帧动画,关键帧动画引入了动画占比时长的概念,这让我们能控制每个关键帧动画的占用比例而不是传入一个无意义的动画时长 —— 这让我们的代码更加难以理解。当然,除了动画占比之外,关键帧动画的options参数也让动画变得更加平滑,下面是关键帧特有的配置参数:

UIViewKeyframeAnimationOptionCalculationModeLinear // 连续运算模式,线性
UIViewKeyframeAnimationOptionCalculationModeDiscrete // 离散运算模式,只显示关键帧
UIViewKeyframeAnimationOptionCalculationModePaced // 均匀执行运算模式,线性
UIViewKeyframeAnimationOptionCalculationModeCubic // 平滑运算模式
UIViewKeyframeAnimationOptionCalculationModeCubicPaced // 平滑均匀运算模式

3. CAAnimationGroup 组合动画

  • Group也就是组合的意思,可以保存一组动画对象,将CAAnimationGroup对象加入图层后,组中所有动画对象可以同时并发运行
  • animations属性:用来保存一组动画对象的NSArray
  • 注意:默认情况下,一组动画对象是同时运行的,也 可以通过设置动画对象的beginTime属性来更改动画的开始时间
-(void)groupAnimation1{
// //位移动画
  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"];
  }

组合动画

PS:一个layer设定了很多动画,他们都会同时执行,而且是顺序执行。(详见demo)

4. CATransition 系统封装的过渡动画

  • 对于UIView的动画

UIViewAnimationTransition 声明过渡方向UIViewAnimationTransitionFlipFromLeft向左转动UIViewAnimationTransitionFlipFromRight向右转动UIViewAnimationTransitionCurlUp向上翻动UIViewAnimationTransitionCurlDown向下翻动

//写法一
-(void)test
{
  [UIView beginAnimations:@"animationID" context:nil];
  [UIView setAnimationDuration:0.5f]; //动画时长
  [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
  [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES]; //给视图添加过渡效果
//在这里写你的代码.
  [UIView commitAnimations]; //提交动画
}
\#pragma UIView实现动画
- (void) animationWithView : (UIView *)view WithAnimationTransition : (UIViewAnimationTransition) transition
{
    [UIView animateWithDuration:DURATION animations:^{
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationTransition:transition forView:view cache:YES];
    }];
}
  • 对于layer的动画

名称 CATransition.type过渡效果kCATransitionFade//淡入淡出 (不支持过渡方向)kCATransitionPush,//推挤kCATransitionReveal//揭开kCATransitionMoveIn//覆盖Cube//立方体SuckEffect//吮吸OglFlip//翻转rippleEffect//波纹pageCurl//翻页pageUnCurl//反翻页cameraIrisHollowOpen//开镜头 相机镜头打开效果(不支持过渡方向)cameraIrisHollowClose//关镜头 相机镜头打开效果(不支持过渡方向)

CATransition含有type和subtype两个属性,分别的解释是

/* The name of the transition. Current legal transition types include

  • fade',moveIn', push' andreveal'. Defaults to `fade'. */
    @property(copy) NSString *type;

/* An optional subtype for the transition. E.g. used to specify the

  • transition direction for motion-based transitions, in which case
  • the legal values are fromLeft',fromRight', `fromTop' and
  • `fromBottom'. */
    @property(nullable, copy) NSString *subtype;

由此可见设置CATransition动画就是动画效果和方向的结合

//写法二
\#pragma CATransition动画实现
- (void) transitionWithType:(NSString *) type WithSubtype:(NSString *) subtype ForView : (UIView *) view
{
    //创建CATransition对象
    CATransition *animation = [CATransition animation];
    //设置运动时间
    animation.duration = DURATION;
    //设置运动type
    animation.type = type;
    if (subtype != nil) {
        //设置子类
        animation.subtype = subtype;
    }
    //设置运动速度
    animation.timingFunction = UIViewAnimationOptionCurveEaseInOut;
    [view.layer addAnimation:animation forKey:@"animation"];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容