×

iOS动画CAKeyframeAnimation

前端技术网 前端技术网 发表于2023-12-19 09:50:09 浏览985 评论0

抢沙发发表评论

一、iOS动画CoreAnimation总结

CoreAnimation翻译过来就是核心动画,一组非常强大的API,用来做动画的,非常的简单但是效果非常绚丽。

CoreAnimation类的继承关系图如下,其中CAMediaTiming是一个协议(protocol)

iOS动画CAKeyframeAnimation

注意:

能用的动画类只剩下4个:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup

2. timingFunction:控制动画运行的节奏。

animationWithKeyPath苹果官方介绍传送门

上文讲到可用的四个动画类:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup。iOS9之后还有CASpringAnimation。先分别针对每个动画类写实例以进行加深。

关键帧动画,也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:

iOS动画CAKeyframeAnimation

关键属性说明:

实例:

动画属性:

属性说明:

实例:

相关属性:

实例:

参考文章:

iOS CAAnimation核心动画

iOS动画之CAKeyframeAnimation

iOS出门必备之CoreAnimation(核心动画)

二、iOS 8自定义动画转场上手指南

篇一:iOS 8自定义动画转场上手指南

iOS 5发布的时候,苹果针对应用程序界面的设计,提出了一种全新的,革命性的方法—Storyboard,它从根本上改变了现有的设计理念。iOS 5之前,每个视图控制器通常都伴有一个Interface Builder的文件,叫nib或者xib,这个想法比较简单:每个视图控制器的界面应该在各自的nib文件中设计,而所有的nib文件一起构成了整个应用程序的界面。一方面,这个是很方便的,因为它强迫开发者在界面设计的时候将注意力集中在界面上,但另一方面,到最后,太多的文件不得不被创建,开发者将不能概览应用的整体界面。

随着storyboard的产生,上面的这些都成为了历史,因为这种新方法受到了开发者社区的广泛使用。相比老的技术,storyboards提供了三个重要的优势:

整个界面设计只发生在一个文件里。项目的总文件数量大大减少了,特别是在大项目里。当然你可以使用额外的nib文件,并且允许只创建辅助视图。

开发者能即时浏览应用的界面和流程。视图控制器之间的转换(界面设计的专业术语叫场景(scene)),以及转换是如何发生的,在storyboard中已被完美地定义并清楚地呈现给了开发者。

综上所述,场景之间的转换构成storyboard的特殊部分,我们一般把它叫做转场(segue)。

转场跟应用的导航和处理是密切相关的,因为它明确定义了一个视图切换到另一个视图的转换细节。这些细节指定了是否应用动画,动画的类型,当然还有实际转换时的准备和性能。除此之外,转场也用来将传递数据到下一个视图控制器里,这个用法也很常见。

从编程的角度看,场景是UIStoryboardSegue类的一个对象,它第一次在iOS 5中介绍到。和其它类的对象

不同的是,这种对象不能直接的创建或使用。不过你可以指定转场的属性,然后在转场即将发生时提供给它以达到目的。UIKit框架提供了一些带默认动画过渡的预定义的转场,包括:push segues(包括导航控制器的app),带有动画选择的模态转场(modal segues), popover segues。更高级的情况下,iOS SDK默认的转场可能不够用,所以开发者必须实现他们的自定义转场(custom segues)。创建一个自定义转场并不难,因为它是iOS标准编程技术的组成部分。实际上你只需要生成UIStoryboardSegue的子类,并重载一个叫perform的方法即可。这个perform方法中必须实现自定义动画的逻辑。从一个视图控制器转换到另一个以及返回操作的触发,也需要由开发者编程提供,这是一个标准的步骤。在本教程中,我的目标是向你们展示如何实现自定义转场,并通过一个简单的演示应用介绍这个概念的所有方面。拥有创建自定义转场的知识,可以将你导

向开发更强大的app的道路。此外,对于最大化用户体验,并开发引人注目的漂亮应用,自定义转场也很有帮助。如果你有兴趣学习我刚刚说的话,就一起来探索教程里的`所有细节和自定义转场的奥秘吧。

应用程序概述不像我之前几个教程提供了一个启动项目,本教程我们将从头开始创建app。事实上,我是故意这么做的,因为,项目中一些重要部分需要用到Interface Builder,所以我认为从头开始按部就班的来做,能让你看清里面的细节。

正如我先前所说,我们将开发一个非常简单的app,在这个应用中我们将创建两个自定义转场。需要提前说明的是,我们的演示应用将有三个视图控制器,也就是在Interface Builder中有三个场景和三个相关类。默认情况下,第一个是由Xcode创建的,因此我们只要再添加两个。我们将创建的自定义转场用来导航第一个视图控制器到第二个

(以及返回),以及从第一个到第三个(以及返回)。第二个和第三个视图控制器之间我们不添加任何联系。

因此,我们需要创建两个自定义转场。因为要包括返回,每一个转场需要创建两个对应的类(因此,共四个):第一个类里我们将实现从第一个视图控制器到另一个转换的所有自定义逻辑。第二个类实现返回到第一个视图控制器的逻辑,或者换句话说要实现解除转场(unwind segue)。后面会讲到解除转场,现在只需要记住这就是用来让我们返回到前一个视图控制器的转场。

视图控制器本身没什么需要做的。我们会用一个label注明视图控制器的名称,每一个会有一个不同的背景颜色,可以让我们很容易地查看转换(是的,这将是一个五颜六色的应用)。第一个和第二个视图控制器也会多一个label,其中从其他视图控制器传来的自定义的消息将被显示出来。

最后,转场将在以下的动作发生的时候

篇二:Swift常用UIView Animation API使用

Swift常用UIView Animation API使用

本文默认读者有基础动画编写能力

参数解释

*如解释有误,请指出,谢谢*

1 duration:动画执行时间

2 delay:动画延迟执行时间

3 options:

.Repeat:动画永远重复的运行

.Autoreverse:动画执行结束后按照相反的行为继续执行。该属性只能和.Repeat属性组合使用

.CurveLinear:动画做线性运动

.CurveEaseIn:动画缓慢开始,然后逐渐加速

.CurveEaseOut:动画迅速开始,在结束时减速

.CurveEaseInOut:动画慢慢开始,然后加速,在结束之前减速.TransitionNone:没有转场动画

.TransitionFlipFromTop:从顶部围绕水平轴做翻转动画.TransitionFlipFromBottom:从底部围绕水平轴做翻转动画

.TransitionFlipFromLeft:从左侧围绕垂直轴做翻转动画

.TransitionFlipFromRight:从右侧围绕垂直轴做翻转动画

.TransitionCurlUp:从下往上做翻页动画

.TransitionCurlDown:从上往下做翻页动画

.TransitionCrossDissolve:视图溶解消失显示新视图动画

4 usingSpringWithDamping:弹簧阻力,取值范围为0.0-1.0,数值越小“弹簧”振动效果越明显。

5 initialSpringVelocity:动画初始的速度(pt/s),数值越大初始速度越快。但要注意的是,初始速度取值较高而时间较短时,也会出现反弹情况。普通动画

animateWithDuration:delay:options:animations:completion: class func animateWithDuration(_ duration: NSTimeInterval,

delay delay: NSTimeInterval,

options options: UIViewAnimationOptions,

animations animations:()-> Void,

completion completion:((Bool)-> Void))

Animate changes to one or more views using the specified duration, delay, options, and completion handler.

对一个或者多个视图按照相应参数做固定动画(翻译纯属个人见解,有错请指出)

animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:

class func animateWithDuration(_ duration: NSTimeInterval,

delay delay: NSTimeInterval,

usingSpringWithDamping dampingRatio: CGFloat,

initialSpringVelocity velocity: CGFloat,

options options: UIViewAnimationOptions,

animations animations:()-> Void,

completion completion:((Bool)-> Void))

Performs a view animation using a timing curve corresponding to the motion of a physical spring.

对一个视图按照相应参数做弹性动画(类似于弹簧,翻译纯属个人见解,有错请指出)

图片借鉴Renfei Song's Blog,只为更清楚的展示调用两个API的不同效果

Spring Animation和普通的动画的运动曲线的对比:

Spring Animation, Ease-Out Animation和 Linear Animation的动画效果:

转场动画

transitionWithView:duration:options:animations:completion: class func transitionWithView(_ view: UIView,

duration duration: NSTimeInterval,

options options: UIViewAnimationOptions,

animations animations:(()-> Void),

completion completion:((Bool)-> Void))

Creates a transition animation for the specified container view.为指定的视图构建一个过渡动画(翻译纯属个人见解,有错请指出)transitionFromView:toView:duration:options:completion:

class func transitionFromView(_ fromView: UIView,

toView toView: UIView,

duration duration: NSTimeInterval,

options options: UIViewAnimationOptions,

completion completion:((Bool)-> Void))

Creates a transition animation between the specified views using the given parameters.

在两个给定视图之间构建过渡动画(翻译纯属个人见解,有错请指出)

以上为UIView Animation的基础动画API,使用其实很简单,就是要理解不同参数的意义。

篇三:iOS开发学习之核心动画

核心动画基本概念

基础动画(CABasicAnimation)

关键帧动画(CAKeyframeAnimation)

动画组

转场动画-CATransition

UIView的转场动画-双视图

一、核心动画基本概念

1.导入QuartzCore.framework框架

开发步骤

1).初始化一个动画对象(CAAnimation)并且设置一些动画相关属性

2).CALayer中很多属性都可以通过CAAnimation实现动画效果,包括:opacity、position、transform、bounds、contents等(可以在API文档中搜索:CALayer Animatable Properties)

3).添加动画对象到层(CALayer)中,开始执行动画

4).通过调用CALayer的addAnimation:forKey增加动画到层(CALayer)中,这样就能触发动画。通过调用removeAnimationForKey可以停止层中的动画

5).Core Animation的动画执行过程都是后台操作的,不会阻塞主线程

2.属性

1).duration:动画的持续时间

2).repeatCount:重复次数(HUGE_VALF、MAX FLOAT无限重复)

3).repeatDuration:重复时间(用的很少)

4).removedOnCompletion:默认为Yes。动画执行完后默认会从图层删除掉

5).fillMode

6).biginTime

7).timingFunction:速度控制函数,控制动画节奏

8).delegate

二、基础动画(CABasicAnimation)

如果只是实现简单属性变化的动画效果,可以使用UIView的块动画替代基本动画

1.属性说明

-fromValue:keyPath相应属性值的初始值

-toValue:keyPath相应属性的结束值

2.动画过程说明:

-随着动画的就行,在duration的持续时间内,keyPath相应的属性值从fromValue渐渐变为toValue

-keyPath内容是CALayer的可动画Animation属性

-如果fillMode=kCAFillModeForwards同时removedOnCompletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态,但在实质上,图层的属性值还是动画执行前的初始值,并没有真正改变

3.代码实现

位移需要考虑目标点设定的问题

1.将动画的所有方法封装到一个类里面

MyCAHelper.h

#import

#import

#define kCAHelperAlphaAnimation@"opacity";//淡入淡出动画#define kCAHelperScaleAnimation@"transform.scale";//比例缩放动画

#define kCAHelperRotationAnimation@"transform.rotation";//旋转动画

#define kCAHelperPositionAnimation@"position";//平移位置动画

@interface MyCAHelper: NSObject

#pragma mark-基本动画统一调用方法

+(CABasicAnimation*)myBasicAnimationWithType:(NSString*)animationTypeduration:(CFTimeInterval)duration from:(NSValue*)from

to:(NSValue*)to

autoRevereses:(BOOL)autoRevereses;

#pragma mark-关键帧动画方法

#pragma mark摇晃动画

+(CAKeyframeAnimation

*)myKeyShakeAnimationWithDuration:(CFTimeInterval)duration

angle:(CGFloat)angle

repeatCount:(CGFloat)repeatCount;

#pragma mark贝塞尔路径动画

+(CAKeyframeAnimation*)myKeyPathAnimationWithDuration:(CFTimeInterval)durationpath:(UIBezierPath*)path;

#pragma mark弹力仿真动画

+(CAKeyframeAnimation*)myKeyBounceAnimationFrom:(CGPoint)from

to:(CGPoint)to

duration:(CFTimeInterval)duration;

@end

MyCAHelper.m

#import"MyCAHelper.h"

@implementation MyCAHelper

#pragma mark-基本动画统一调用方法

+(CABasicAnimation*)myBasicAnimationWithType:(NSString*)animationTypeduration:(CFTimeInterval)duration

from:(NSValue*)from

to:(NSValue*)to

autoRevereses:(BOOL)autoRevereses

{

// 1.实例化一个CA动画对象

CABasicAnimation*anim= [CABasicAnimation animationWithKeyPath:animationType];

// 2.设置动画属性

[anim setDuration:duration];

[anim setFromValue:from];

[anim setToValue:to];

[anim setAutoreverses:autoRevereses];

return anim;

}

#pragma mark-关键帧动画方法

#pragma mark摇晃动画

+(CAKeyframeAnimation

*)myKeyShakeAnimationWithDuration:(CFTimeInterval)duration

angle:(CGFloat)angle

repeatCount:(CGFloat)repeatCount

{

// 1.初始化动画对象实例

CAKeyframeAnimation*anim= [CAKeyframeAnimation

animationWithKeyPath:@"transform.rotation"];

// 2.设置动画属性

[anim setDuration:duration];

[anim setValues:@[@(angle),@(-angle),@(angle)]];

[anim setRepeatCount:repeatCount];

return anim;

}

#pragma mark贝塞尔路径动画

+(CAKeyframeAnimation*)myKeyPathAnimationWithDuration:(CFTimeInterval)duration path:(UIBezierPath*)path

{

// 1.初始化动画对象实例

CAKeyframeAnimation*anim= [CAKeyframeAnimation

animationWithKeyPath:@"position"];

// 2.设置动画属性

[anim setDuration:duration];

三、iOS核心动画之图片旋转、脉冲动画、水波纹动画

下边有整体效果,希望能帮助到你!

定义一个视图

@property(weak, nonatomic) IBOutlet UIImageView*imageView;

一、图片旋转三种方式:

第一种:根据CGPathAddArc绘画图片旋转路线:

/*

    1、<#CGMutablePathRef  _Nullable path#>路线

    2、确定圆心<#CGFloat x#><#CGFloat y#>

    3、半径<#CGFloat radius#>

    4、起点<#CGFloat startAngle#>结束<#CGFloat endAngle#>

  */

 CGPathAddArc(path, NULL, self.view.center.x, self.view.center.y, 0.1, 0, M_PI*2, 1);

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

   frameAnimation.path= path;

   CGPathRelease(path);

   frameAnimation.delegate=self;

   frameAnimation.duration=10;//持续时间

   frameAnimation.repeatCount=-1;//重复次数如果为0表示不执行,-1表示不限制次数,默认为0

   frameAnimation.autoreverses=NO;

   frameAnimation.rotationMode= kCAAnimationRotateAuto;//样式

   frameAnimation.fillMode= kCAFillModeForwards;

   [self.imageView.layeraddAnimation:frameAnimationforKey:nil];

第二种:

 [UIView animateWithDuration:20.0f animations:^{

     if(self.imageView){

      self.imageView.transform= CGAffineTransformMakeRotation(M_PI*5);

       }

  }];

第三种:

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

  //默认是顺时针效果,若将fromValue和toValue的值互换,则为逆时针效果

   animation.fromValue= [NSNumber numberWithFloat:0.f];

   animation.toValue= [NSNumber numberWithFloat: M_PI*2];

   animation.duration=30;

   animation.autoreverses=NO;

   animation.fillMode= kCAFillModeForwards;

   animation.repeatCount= MAXFLOAT;//如果这里想设置成一直自旋转,可以设置为MAXFLOAT,否则设置具体的数值则代表执行多少次

   [self.imageView.layer addAnimation:animation forKey:nil];

持续旋转:

@property(nonatomic,assign) double angle;

 CGAffineTransform endAngle= CGAffineTransformMakeRotation(self.angle*(M_PI/ 180.0f));

   [UIView animateWithDuration:0.01 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{

     self.imageView.transform= endAngle;

  }completion:^(BOOLfinished){

     self.angle+=10;

     [self startAnimation2];//上边任意一种方法回调

  }];

//当视图停止转动时调用此方法重新转动

-(void)endAnimation{

   self.angle+=4;

   [self startAnimation2];

}

二、水波纹动画

属性定义:几个波纹定义几个X宽度可以用一个也可以分开定义

  @property(weak, nonatomic) IBOutlet UIView*backView;

@property(nonatomic,strong) CAShapeLayer* waterLayer1;

@property(nonatomic,strong) CAShapeLayer* waterLayer2;

@property(nonatomic,assign) CGFloat x;

@property(nonatomic,assign) CGFloat y;

@property(nonatomic,assign) CGFloat waveHeight;

@property(nonatomic,assign) CGFloat waveWidth;

@property(nonatomic,assign) int speedWave;

@property(nonatomic,assign) CGFloat waveAmplitude;

@property(nonatomic,assign) int speed;

@property(nonatomic,assign) CGFloat speed_H;

@property(nonatomic,assign) CGFloat offsetXT;

-(instancetype)init{//给个初始值,下边被除数不能为0

    if(self== [super init]){

         self.speedWave= 3;

      self.waveAmplitude= 3;

      self.speed=3;

      self.waveWidth= self.backView.frame.size.width;

      self.waveHeight= self.backView.frame.size.height;

      self.speed_H= self.backView.frame.size.height-20;

    }

return self;

}

-(void)waterAnimation{

//   CGFloat y= _waveHeight*sinf(2.5*M_PI*i/_waveWidth+ 3*_offset*M_PI/_waveWidth+ M_PI/4)+ _h;

   self.waterLayer1= [CAShapeLayer layer];

   self.waterLayer1.fillColor= [UIColor yellowColor].CGColor;

   [self.backView.layer addSublayer:self.waterLayer1];

   self.waterLayer2= [CAShapeLayer layer];

    self.waterLayer2.fillColor= [UIColor redColor].CGColor;

   [self.backView.layer addSublayer: self.waterLayer2];

  //创建一个新的 CADisplayLink对象,把它添加到一个runloop中,并给它提供一个 target和selector在屏幕刷新的时候调用

  //CADispayLink相当于一个定时器会一直绘制曲线波纹看似在运动,其实是一直在绘画不同位置点的余弦函数曲线

   CADisplayLink* waveDisplayLink= [CADisplayLink displayLinkWithTarget:self selector:@selector(getCurrentWave)];

   [waveDisplayLinkaddToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

}

-(void)getCurrentWave{

  // x位置

   self.x+=self.speed;

  //声明第一条波曲线的路径

   CGMutablePathRef path= CGPathCreateMutable();

  //设置起始点

   CGPathMoveToPoint(path,nil,0,self.waveHeight);

   CGFloaty=0.f;

  //第一个波纹的公式

   for(floatx=0.f; x<=self.waveWidth; x++){

     y=self.waveAmplitude*sin((200/self.waveWidth)*(x*M_PI/70)-self.x*M_PI/170)+self.speed_H*1;

     CGPathAddLineToPoint(path,nil, x, y);

     x++;

  }

  //把绘图信息添加到路径里

   CGPathAddLineToPoint(path, nil, self.waveWidth, self.backView.frame.size.height);

   CGPathAddLineToPoint(path, nil, 0, self.backView.frame.size.height);

  //结束绘图信息

   CGPathCloseSubpath(path);

   self.waterLayer1.path= path;

  //释放绘图路径

   CGPathRelease(path);

   [self   X2];

}

///第二条水波

-(void)X2{

   self.offsetXT+= self.speedWave;

   CGMutablePathRef pathT= CGPathCreateMutable();

   CGPathMoveToPoint(pathT,nil,0,self.waveHeight+50);

   CGFloatyT=0.f;

   for(floatx=0.f; x<=self.waveWidth; x++){

     yT=self.waveAmplitude*1.6*sin((200/self.waveWidth)*(x*M_PI/100)-self.offsetXT*M_PI/170)+self.waveHeight;

     CGPathAddLineToPoint(pathT,nil, x, yT-10);

  }

   CGPathAddLineToPoint(pathT, nil, self.waveWidth, self.backView.frame.size.height);

   CGPathAddLineToPoint(pathT, nil, 0, self.backView.frame.size.height);

   CGPathCloseSubpath(pathT);

   self.waterLayer2.path= pathT;

   CGPathRelease(pathT);

}

三、脉冲效果动画

@property(weak, nonatomic) IBOutlet UIView*pulseView;

@property(nonatomic,strong) CAShapeLayer* pulseLayer;

-(void)pulseAnimation{

   CGFloat width= self.pulseView.bounds.size.width;

   self.pulseLayer= [CAShapeLayer layer];

   self.pulseLayer.bounds=CGRectMake(0,0, width, width);

   self.pulseLayer.position=CGPointMake(width/2, width/2);

   self.pulseLayer.backgroundColor= [UIColor clearColor].CGColor;

   self.pulseLayer.path= [UIBezierPath bezierPathWithOvalInRect:self.pulseLayer.bounds].CGPath;

   self.pulseLayer.fillColor= [UIColor colorWithRed: 0.3490196078 green:0.737254902 blue:0.8039215686 alpha:1].CGColor;

   self.pulseLayer.opacity= 0.0;

   CAReplicatorLayer* replicatorLayer= [CAReplicatorLayer layer];

   replicatorLayer.bounds=CGRectMake(0,0, width, width);

   replicatorLayer.position=CGPointMake(width/2, width/2);

   replicatorLayer.instanceCount=4;//**层

   replicatorLayer.instanceDelay=1;///频率

   [replicatorLayeraddSublayer:self.pulseLayer];

   [self.pulseView.layeraddSublayer:replicatorLayer];

   [self.pulseView.layerinsertSublayer:replicatorLayeratIndex:0];

}

-(void)startPulseAnimation{

   CABasicAnimation* opacityAnimation= [CABasicAnimation animationWithKeyPath:@"opacity"];

   opacityAnimation.fromValue=@20;//起始值(strong修饰的id值)

   opacityAnimation.toValue=@30;//结束值(strong修饰的id值)

   CABasicAnimation* scaleAnimation= [CABasicAnimation animationWithKeyPath:@"transform"];

   scaleAnimation.fromValue= [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 0.0, 0.0, 0.0)];

   scaleAnimation.toValue=[NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 1.0)];

   CAAnimationGroup* groupAnimation= [CAAnimationGroup animation];

   groupAnimation.animations=@[opacityAnimation, scaleAnimation];

   groupAnimation.duration=20;

   groupAnimation.autoreverses=NO;

   groupAnimation.repeatCount=HUGE;

   [self.pulseLayeraddAnimation:groupAnimationforKey:nil];

}

在此附上效果:

听说有好得三方库,我还没有去找过,欢迎各位大佬推荐一个优质的三方。。。。。

喜欢的朋友点个赞呗!

如果你还想了解更多这方面的信息,记得收藏关注本站。