iOS - Core Animation 核心动画

1、UIView 动画

  • 具体讲解见 iOS - UIView 动画

2、UIImageView 动画

  • 具体讲解见 iOS - UIImageView 动画

3、CADisplayLink 定时器

  • 具体讲解见 iOS - OC NSTimer 定时器

  • CADisplayLink 是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器。我们在应用中创建一个新的 CADisplayLink 对象,把它添加到一个 runloop 中,并给它提供一个 target 和 selector 在屏幕刷新的时候调用。

  • CADisplayLink 使用场合相对专一,适合做 UI 的不停重绘,比如自定义动画引擎或者视频播放的渲染。NSTimer 的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。在 UI 相关的动画或者显示内容使用 CADisplayLink 比起用 NSTimer 的好处就是我们不需要再格外关心屏幕的刷新频率了,因为它本身就是跟屏幕刷新同步的。

4、CALayer 绘图层

  • 具体讲解见 iOS - CALayer 绘图层

  • 在 iOS 系统中,你能看得见摸得着的东西基本上都是 UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是 UIView。其实 UIView 之所以能显示在屏幕上,完全是因为它内部的一个层。在创建 UIView 对象时,UIView 内部会自动创建一个层(即 CALayer 对象),通过 UIView 的 layer 属性可以访问这个层。当 UIView 需要显示到屏幕上时,会调用 drawRect: 方法进行绘图,并且会将所有内容绘制在自己的层上,绘图完毕后,系统会将层拷贝到屏幕上,于是就完成了 UIView 的显示。换句话说,UIView 本身不具备显示的功能,是它内部的层才有显示功能。

5、核心动画基本概念

  • Core Animation 中文翻译为核心动画,它是一组非常强大的动画处理 API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。也就是说,使用少量的代码就可以实现非常强大的功能。Core Animation 可以用在 macOS 和 iOS 平台。乔帮主在 2007 年的 WWDC 大会上亲自为你演示 Core Animation 的强大:点击查看视频。

  • Core Animation 的动画执行过程都是在后台操作的,不会阻塞主线程。

  • 要注意的是,Core Animation 是直接作用在 CALayer 上的,并非 UIView。

  • 核心动画 和 UIView 动画 的区别:

    • 核心动画一切都是假象,并不会真实的改变图层的属性值,如果以后做动画的时候,不需要与用户交互,通常用核心动画(转场)。
    • UIView 动画必须通过修改属性的真实值,才有动画效果。

5.1 核心动画继承结构

  • 核心动画继承结构

    animation30

5.2 核心动画使用步骤

  • Xcode6 之前的版本,使用它需要先添加 QuartzCore.framework 和引入对应的框架 <QuartzCore/QuartzCore.h>

  • 开发步骤:

    • 1、首先得有 CALayer。
    • 2、初始化一个 CAAnimation 对象,并设置一些动画相关属性。
    • 3、通过调用 CALayer 的 addAnimation:forKey: 方法,增加 CAAnimation 对象到 CALayer 中,这样就能开始执行动画了。
    • 4、通过调用 CALayer 的 removeAnimationForKey: 方法可以停止 CALayer 中的动画。

5.3 CAAnimation

  • 1、CAAnimation 简介

    • CAAnimation 是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类。

    • 属性说明:

          removedOnCompletion :默认为 YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为 NO,不过还要设置 fillMode 为 kCAFillModeForwards。timingFunction      :速度控制函数,控制动画运行的节奏。delegate            :动画代理,需要遵守协议 CAAnimationDelegate。// 来自 CAMediaTiming 协议的属性duration       :动画的持续时间。repeatCount    :重复次数,无限循环可以设置 HUGE_VALF 或者 MAXFLOAT。repeatDuration :重复时间。fillMode       :决定当前对象在非 active 时间段的行为。比如动画开始之前或者动画结束之后。beginTime      :可以用来设置动画延迟执行时间,若想延迟 2s,就设置为 CACurrentMediaTime()+2,CACurrentMediaTime() 为图层的当前时间。
  • 2、CAAnimation 动画填充模式

    • 设置 fillMode 属性值(要想 fillMode 有效,需要设置 removedOnCompletion = NO)

          kCAFillModeRemoved   :这个是默认值,也就是说当动画开始前和动画结束后,动画对 layer 都没有影响,动画结束后,layer 会恢复到之前的状态。kCAFillModeForwards  :当动画结束后,layer 会一直保持着动画最后的状态。kCAFillModeBackwards :在动画开始前,只需要将动画加入了一个 layer,layer 便立即进入动画的初始状态并等待动画开始。kCAFillModeBoth      :这个其实就是上面两个的合成,动画加入后开始之前,layer 便处于动画初始状态,动画结束后 layer 保持动画最后的状态。
  • 3、CAAnimation 速度控制函数

    • CAMediaTimingFunction 速度控制函数

          kCAMediaTimingFunctionLinear        :线性,匀速,给你一个相对静态的感觉。kCAMediaTimingFunctionEaseIn        :渐进,动画缓慢进入,然后加速离开。kCAMediaTimingFunctionEaseOut       :渐出,动画全速进入,然后减速的到达目的地。kCAMediaTimingFunctionEaseInEaseOut :渐进渐出,动画缓慢的进入,中间加速,然后减速的到达目的地。这个是默认的动画行为。
  • 4、CAAnimation 动画代理方法

    • CAAnimation 在分类中定义了代理方法

          @interface NSObject (CAAnimationDelegate)/* Called when the animation begins its active duration. */// 动画开始执行的时候触发这个方法- (void)animationDidStart:(CAAnimation *)anim;/* Called when the animation either completes its active duration or* is removed from the object it is attached to (i.e. the layer). 'flag'* is true if the animation reached the end of its active duration* without being removed. */// 动画执行完毕的时候触发这个方法- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;@end

5.4 CAPropertyAnimation

  • CAPropertyAnimation 是 CAAnimation 的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:
    • CABasicAnimation
    • CAKeyframeAnimation
  • 属性说明:

        keyPath :通过指定 CALayer 的一个属性名称为 keyPath(NSString 类型),并且对 CALayer 的这个属性的值进行修改,达到相应的动画效果。比如,指定 @“position” 为 keyPath,就修改 CALayer 的 position 属性的值,以达到平移的动画效果。

5.5 CALayer 上动画的暂停和恢复

  • 1、CALayer 上动画的暂停

        // 暂停 CALayer 的动画,自定义方法- (void)pauseLayer:(CALayer*)layer {CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];// 让 CALayer 的时间停止走动layer.speed = 0.0;// 让 CALayer 的时间停留在 pausedTime 这个时刻layer.timeOffset = pausedTime;}
  • 2、CALayer 上动画的恢复

        // 恢复 CALayer 的动画,自定义方法- (void)resumeLayer:(CALayer*)layer {CFTimeInterval pausedTime = layer.timeOffset;// 让 CALayer 的时间继续行走layer.speed = 1.0;// 取消上次记录的停留时刻layer.timeOffset = 0.0;// 取消上次设置的时间layer.beginTime = 0.0;// 计算暂停的时间(这里也可以用 CACurrentMediaTime() - pausedTime)CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;// 设置相对于父坐标系的开始时间(往后退 timeSincePause)layer.beginTime = timeSincePause;}

6、基本动画

  • CABasicAnimation 基本动画,是 CAPropertyAnimation 的子类。

  • 属性说明:

        fromValue :keyPath 相应属性的初始值toValue   :keyPath 相应属性的结束值byValue   :keyPath 相应属性的改变值
  • 动画过程说明:

    • keyPath 内容是 CALayer 的可动画 Animatable 属性。
    • 随着动画的进行,在长度为 duration 的持续时间内,keyPath 相应属性的值从 fromValue 渐渐地变为 toValue。
    • 如果 fillMode = kCAFillModeForwards 同时 removedOnComletion = NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。
  • CABasicAnimation 虽然能够做很多基本的动画效果,但是有个局限性,只能让 CALayer 的属性从某个值渐变到另一个值,仅仅是在 2 个值之间渐变。

6.1 平移动画

  • 1、方法 1

        // 说明这个动画对象要对 CALayer 的 position 属性执行动画CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];// 动画持续 1.5sanim.duration = 1.5;// position 属性值从 (50, 80) 渐变到 (300, 350)anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(50, 80)];anim.toValue = [NSValue valueWithCGPoint:CGPointMake(250, 350)];// 设置动画的代理anim.delegate = self;// 保持动画执行后的状态anim.removedOnCompletion = NO;anim.fillMode = kCAFillModeForwards;// 添加动画对象到图层上[self.myView.layer addAnimation:anim forKey:@"translate"];
    • 第 2 行设置的 keyPath 是 @"position",说明要修改的是 CALayer 的 position 属性,也就是会执行平移动画。

    • 注意第 8、9 行,这里并不是直接使用 CGPoint 这种结构体类型,而是要先包装成 NSValue 对象后再使用。这 2 行代码表示 CALayer 从位置 (50, 80) 移动到位置 (250, 350)。

    • 如果将第 9 行的 toValue 换成 byValue,代表 CALayer 从位置 (50, 80) 开始向右移动 250、向下移动 350,也就是移动到位置 (300, 430)。

          anim.byValue = [NSValue valueWithCGPoint:CGPointMake(250, 350)];
    • 默认情况下,动画执行完毕后,动画会自动从 CALayer 上移除,CALayer 又会回到原来的状态。为了保持动画执行后的状态,可以加入第 15、16 行代码。

    • 第 19 行后面的 @"translate" 是给动画对象起个名称,以后可以调用 CALayer 的 removeAnimationForKey: 方法根据动画名称停止相应的动画。

    • 第 12 行是设置动画的代理,可以监听动画的执行过程,这里设置控制器为代理。需要遵守协议 CAAnimationDelegate,代理需要实现的方法有:

          - (void)animationDidStart:(CAAnimation *)anim {NSLog(@"%s", __func__);}- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {NSLog(@"%s", __func__);}
    • 打印结果为:

          09:11:10.880 CALayerDemo[12721:622836] -[ViewController animationDidStart:]09:11:12.419 CALayerDemo[12721:622836] -[ViewController animationDidStop:finished:],position:{50, 80}
    • 实际上,动画执行完毕后,并没有真正改变 CALayer 的 position 属性的值。

    • 效果

      animation32

  • 2、方法 2

        // 说明这个动画对象要对 CALayer 的 transform 属性执行动画CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];// 动画持续 1.5sanim.duration = 1.5;// 平移,x 轴移动 250,y 轴移动 350,z 轴移动 0CATransform3D form = CATransform3DMakeTranslation(250, 350, 0);anim.toValue = [NSValue valueWithCATransform3D:form];// 添加动画对象到图层上[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation33

6.2 缩放动画

  • 1、方法 1

        // 说明这个动画对象要对 CALayer 的 bounds 属性执行动画CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"bounds"];// 动画持续 2sanim.duration = 2;// 缩放,width 从 100 变为 30,height 从 100 变为 30// anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];  // fromValue 可以省略anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 30, 30)];// 添加动画对象到图层上[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation34

  • 2、方法 2

        // 说明这个动画对象要对 CALayer 的 transform 属性执行动画CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];// 动画持续 1.5sanim.duration = 1.5;// 缩放,width 从 100 变为 200,height 从 100 变为 150// anim.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];anim.toValue  = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2.0, 1.5, 1.0)];// 添加动画对象到图层上[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation35

  • 3、心跳效果

        // 说明这个动画对象要对 CALayer 的 transform.scale 属性执行动画CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];// 动画持续 1.0sanim.duration = 1.0;// 缩放倍数anim.toValue = @0.5;// 设置动画执行次数anim.repeatCount = MAXFLOAT;// 保持动画执行后的状态anim.removedOnCompletion = NO;anim.fillMode = kCAFillModeForwards;// 添加动画对象到图层上[imageView.layer addAnimation:anim forKey:nil];
    • 效果

      animation42

6.3 旋转动画

  • 1、方法

        // 说明这个动画对象要对 CALayer 的 transform.rotation 属性执行动画CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];// 动画持续 3.5sanim.duration = 3.5;// 缩放倍数anim.toValue = @(M_PI_4 * 3);// 添加动画对象到图层上[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation43

  • 2、方法

        // 说明这个动画对象要对 CALayer 的 transform 属性执行动画CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];// 动画持续 3.5sanim.duration = 3.5;// 绕着 (0, 0, 1) 这个向量轴顺时针旋转 45°// anim.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0, 0, 0, 1)];anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4 * 3, 0, 0, 1)];// 设置动画执行次数anim.repeatCount = MAXFLOAT;// 保持动画执行后的状态anim.removedOnCompletion = NO;anim.fillMode = kCAFillModeForwards;// 添加动画对象到图层上[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation36

7、关键帧动画

  • CAKeyframeAnimation 关键帧动画,是 CAPropertyAnimation 的子类。

  • 与 CABasicAnimation 的区别是:

    • CABasicAnimation 只能从一个数值(fromValue)变到另一个数值(toValue),而 CAKeyframeAnimation 会使用一个 NSArray 保存这些数值。
    • CABasicAnimation 可看做是只有2个关键帧的 CAKeyframeAnimation。
  • 属性说明:

        values   :上述的 NSArray 对象。里面的元素称为 “关键帧” (keyframe)。动画对象会在指定的时间(duration)内,依次显示 values 数组中的每一个关键帧。path     :可以设置一个 CGPathRef、CGMutablePathRef,让图层按照路径轨迹移动。path 只对 CALayer 的 anchorPoint 和 position 起作用。如果设置了 path,那么 values 将被忽略。keyTimes :可以为对应的关键帧指定对应的时间点,其取值范围为 0 到 1.0,keyTimes 中的每一个时间值都对应 values 中的每一帧。如果没有设置 keyTimes,各个关键帧的时间是平分的。

7.1 平移动画

  • 1、添加动画关键帧

        CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation"];// CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];anim.duration = 5.0;// 动画起始位置,从 position 点出开始NSValue *pointVal1 = [NSValue valueWithCGPoint:CGPointMake(0, 0)];// 水平移动 200 - 0,垂直方向不变(0 - 0 = 0)NSValue *pointVal2 = [NSValue valueWithCGPoint:CGPointMake(200, 0)];// 垂直移动 200 - 0,水平位置不变(200 - 200 = 0)NSValue *pointVal3 = [NSValue valueWithCGPoint:CGPointMake(200, 200)];// 水平移动 0 - 200,垂直方向不变(200 - 200 = 0)NSValue *pointVal4 = [NSValue valueWithCGPoint:CGPointMake(0, 200)];// 垂直移动 0 - 200,水平位置不变(0 - 0 = 0)NSValue *pointVal5 = [NSValue valueWithCGPoint:CGPointMake(0, 0)];// 添加动画关键帧anim.values = @[pointVal1, pointVal2, pointVal3, pointVal4, pointVal5];[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation44

  • 2、添加动画路径

        CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation"];// CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];anim.duration = 5.0;// 添加动画路径anim.path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 200, 200)].CGPath;[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation44

  • 3、划定路径移动

    • DrawView.m

          @interface DrawView ()@property (nonatomic, strong) UIBezierPath *path;@end@implementation DrawView/// 触摸开始- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {// 移除上一个动画[self.subviews.firstObject.layer removeAnimationForKey:@"drawAnimation"];// 获取触摸起始点位置CGPoint startPoint = [touches.anyObject locationInView:self];// 创建路径self.path = [UIBezierPath bezierPath];// 设置起点[self.path moveToPoint:startPoint];}/// 触摸移动- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {// 获取触摸点位置CGPoint touchPoint = [touches.anyObject locationInView:self];[self.path addLineToPoint:touchPoint];[self setNeedsDisplay];}/// 触摸结束- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {// 添加关键帧动画CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];anim.keyPath = @"position";// 添加动画路径anim.path = self.path.CGPath;anim.duration = 3;anim.repeatCount = MAXFLOAT;anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];// 给子视图添加核心动画[self.subviews.firstObject.layer addAnimation:anim forKey:@"drawAnimation"];}/// 触摸取消- (void)touchesCancelled:(NSSet *)touches withEvent:(nullable UIEvent *)event {[self touchesEnded:touches withEvent:event];}/// 绘图- (void)drawRect:(CGRect)rect {[self.path stroke];}@end
    • ViewController.m

          DrawView *myDrawView = [[DrawView alloc] initWithFrame:self.view.bounds];myDrawView.backgroundColor = [UIColor whiteColor];[self.view addSubview:myDrawView];UIImageView *imv = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 50, 50)];imv.image = [UIImage imageNamed:@"heart2"];[myDrawView addSubview:imv];
      • 效果

        animation47

7.2 缩放动画

  • 缩放动画

        CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];anim.duration = 5.0;// 动画起始大小,1 不缩放NSNumber *scaleVal1 = @1;// 放大 2 倍NSNumber *scaleVal2 = @2;// 不缩放,缩小至原来大小NSNumber *scaleVal3 = @1;// 缩小 0.5 倍NSNumber *scaleVal4 = @0.5;// 不缩放,放大至原来大小NSNumber *scaleVal5 = @1;// 添加动画关键帧anim.values = @[scaleVal1, scaleVal2, scaleVal3, scaleVal4, scaleVal5];[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation45

7.3 旋转动画

  • 1、旋转动画

        CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];anim.duration = 5.0;// 动画起始角度,0 不旋转NSNumber *rotationVal1 = @0;// 旋转 M_PI_4 * 1NSNumber *rotationVal2 = @(M_PI_4 * 1);// 旋转 M_PI_4 * 2NSNumber *rotationVal3 = @(M_PI_4 * 2);// 旋转 M_PI_4 * 3NSNumber *rotationVal4 = @(M_PI_4 * 3);// 旋转 M_PI_4 * 4NSNumber *rotationVal5 = @(M_PI_4 * 4);// 添加动画关键帧anim.values = @[rotationVal1, rotationVal2, rotationVal3, rotationVal4, rotationVal5];[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation46

  • 2、图标抖动

        CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];anim.repeatCount = MAXFLOAT;NSNumber *rotationVal1 = @(-5 / 180.0 * M_PI);NSNumber *rotationVal2 = @(5 / 180.0 * M_PI);NSNumber *rotationVal3 = @(-5 / 180.0 * M_PI);// 添加动画关键帧anim.values = @[rotationVal1, rotationVal2, rotationVal3];[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation48

8、转场动画

  • CATransition 转场动画,是 CAAnimation 的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。UINavigationController 就是通过 CATransition 实现了将控制器的视图推入屏幕的动画效果。

  • 动画属性:

        type          :动画类型。subtype       :动画方向。startProgress :动画起点(在整体动画的百分比)。endProgress   :动画终点(在整体动画的百分比)。
  • 设置动画类型

        基本型:kCATransitionFade      交叉淡化过渡kCATransitionPush      新视图把旧视图推出去kCATransitionMoveIn    新视图移到旧视图上面kCATransitionReveal    将旧视图移开,显示下面的新视图用字符串表示的类型:fade   push   moveIn   reveal   和系统自带的四种一样pageCurl               向上翻页效果pageUnCurl             向下翻页效果rippleEffect           水滴效果suckEffect             收缩效果,如一块布被抽走cube                   立方体翻滚效果alignedCube            立方体翻滚效果flip                   翻转效果alignedFlip            翻转效果oglFlip                翻转效果rotate                 旋转cameraIrisHollowOpen   相机镜头打开效果cameraIrisHollowClose  相机镜头关闭效果cameraIris             相机镜头打开关闭效果
    • kCATransitionFade 和 fade 效果,kCATransitionPush 和 push 效果

      animation50animation51

    • kCATransitionMoveIn 和 moveIn 效果,kCATransitionReveal 和 reveal 效果

      animation52animation53

    • pageCurl 效果,pageUnCurl 效果

      animation54animation55

    • rippleEffect 效果,suckEffect 效果

      animation56animation57

    • cube、alignedCube 效果,flip、alignedFlip、oglFlip 效果

      animation58animation59

    • rotate 效果,cameraIris 效果

      animation60animation61

    • cameraIrisHollowOpen 效果,cameraIrisHollowClose 效果

      animation62animation63

  • 设置动画方向

        四种预设,某些类型中此设置无效:kCATransitionFromRightkCATransitionFromLeftkCATransitionFromTopkCATransitionFromBottom
  • UIView 实现转场动画方法

        // 单视图+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;参数说明:view:需要进行转场动画的视图duration:动画的持续时间options:转场动画的类型animations:将改变视图属性的代码放在这个 block 中completion:动画结束后,会自动调用这个 block// 双视图+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion;参数说明:duration:动画的持续时间options:转场动画的类型completion:动画结束后,会自动调用这个 block

8.1 添加转场动画

  • 添加转场动画

        @property (weak, nonatomic) IBOutlet UIView *animView;@property (weak, nonatomic) IBOutlet UIImageView *imageView;- (IBAction)btnClick:(id)sender {static int i = 2;// 加载图片self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"page%d", i]];i = (i == 2) ? 1 : i + 1;// 添加转场动画CATransition *anim = [CATransition animation];// 设置动画效果anim.type = @"flip";// 设置动画方向anim.subtype = kCATransitionFromLeft;// 设置动画时间anim.duration = 1.0;// 添加转场动画[self.animView.layer addAnimation:anim forKey:nil];}

    animation31

    • 效果

      animation49

9、动画组

  • CAAnimationGroup 动画组,是 CAAnimation 的子类,可以保存一组动画对象,将 CAAnimationGroup 对象加入层后,组中所有动画对象可以同时并发运行。

  • 属性说明:

        animations :用来保存一组动画对象的 NSArray。默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的 beginTime 属性来更改动画的开始时间。

9.1 添加动画组

  • 添加动画组

        // 同时旋转,缩放,平移CAAnimationGroup *anim = [CAAnimationGroup animation];CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];rotation.toValue = @(M_PI_4 * 3);CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];scale.toValue = @0.5;CABasicAnimation *translation = [CABasicAnimation animationWithKeyPath:@"transform.translation"];translation.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 300)];// 添加动画anim.animations = @[rotation, scale, translation];anim.duration = 3.0;anim.removedOnCompletion = NO;anim.fillMode = kCAFillModeForwards;// 添加动画组[self.myView.layer addAnimation:anim forKey:nil];
    • 效果

      animation64

10、核心动画的使用

  • 具体讲解见 iOS - Core Animation 核心动画的使用

转载于:https://www.cnblogs.com/QianChia/p/6359714.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457258.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【BZOJ 1597】 [Usaco2008 Mar]土地购买 (斜率优化)

1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3601 Solved: 1322Description 农夫John准备扩大他的农场,他正在考虑N (1 < N < 50,000) 块长方形的土地. 每块土地的长宽满足(1 < 宽 < 1,000,000; 1 < 长 < 1,000,000). …

深入浅出学java_《深入浅出学JAVA开发初级》

整体说明&#xff1a;Java私塾的这一套视频是完全真实课堂录制&#xff0c;实际上课时间为十一天&#xff0c;主要内容包括&#xff1a;1&#xff1a;系统完整的学习Java的基础知识2&#xff1a;深入剖析重点知识点的理论3&#xff1a;超多的编程题目和程序讲解4&#xff1a;最…

Linux bashrc和profile的用途和区别

导读使用终端ssh登录Linux操作系统的控制台后&#xff0c;会出现一个提示符号&#xff08;例如&#xff1a;#或~&#xff09;&#xff0c;在这个提示符号之后可以输入命令&#xff0c;Linux根据输入的命令会做回应&#xff0c;这一连串的动作是由一个所谓的Shell来做处理。Shel…

Golang 特性简介

by sheepbao 主要大概介绍go语言的历史和特性&#xff0c;简单的入门。 来历 很久以前&#xff0c;有一个IT公司&#xff0c;这公司有个传统&#xff0c;允许员工拥有20%自由时间来开发实验性项目。在2007的某一天&#xff0c;公司的几个大牛&#xff0c;正在用c开发一些比较繁…

华为2017java笔试题_2017年java华为面试题

2017年java华为面试题通过HCNP认证&#xff0c;将证明您对中小型网络有全面深入的了解&#xff0c;掌握中小型网络的通用技术&#xff0c;并具备独立设计中小型网络以及使用华为路由交换设备实施设计的能力。下面是小编收集的关于java华为面试题&#xff0c;希望大家认真阅读!1…

java框架概念_java概念(2)

java概念(2)重载和重写重载&#xff1a;同一个类中&#xff0c;方法名相同&#xff0c;参数不同重写&#xff1a;父子类中&#xff0c;子类重新定义父类的方法多态​ 多态&#xff1a;同一种行为&#xff0c;不同的对象有不同的表现形式。​ 重载 编译时根据参数决定调用的方法…

CentOS(八)--crontab命令的使用方法

crontab命令常见于Unix和Linux的操作系统之中&#xff0c;用于设置周期性被执行的指令。该命令从标准输入设备读取指令&#xff0c;并将其存放于"crontab"文件中&#xff0c;以供之后读取和执行。 在Linux系统中&#xff0c;Linux任务调度的工作主要分为以下两类&…

有健忘症吗?

今天兴高采烈&#xff0c;早上空气不错&#xff0c; 但是骑自行车的我&#xff0c;还是得戴一个面罩。 半个小时后买了早餐&#xff0c; 一份炒粉、一豆浆&#xff0c;今天早上豆浆没有掉地上&#xff0c; 但是~~~~~~~~~~~~~~shit~~!~!~,居然忘记带要换的衣服了&#xff0c; …

下载java后缀的文件闪退_关于jarfile 打开闪退问题

后面才发现&#xff0c;原来是因为我把文件拖入了新建的文件夹&#xff0c;改变了路径&#xff0c;而且我的java环境没有配置好是全局变量&#xff0c;所以新建文件夹之后&#xff0c;就会出现找不到了路径&#xff0c;闪退的问题&#xff0c;&#xff0c;&#xff0c;还有就是…

java怎样写入五个人的成绩_用java输入5个学员姓名和分数,显示分数最高的学员姓名和分数?...

展开全部import java.util.Scanner;public class Student {private String stuname "";private float stuscore 0;public String getStuname() {e69da5e6ba9062616964757a686964616f31333335316633return stuname;}public void setStuname(String stuname) {this.s…

iOS 10 升级后无法真机测试 Could not find Developer Disk Image

&#xff0d;&#xff0d;&#xff0d;2016年9月20日更新 iOS 升级到10之后&#xff0c;你会发现无法进行真机测试了。这种情况我在iOS 8.4 、9.3更新的时候也遇到过。原因是Xcode 的DeviceSupport里面缺少了iOS 10的SDK。所以你可以选择将Xcode更新到最新版本就可以了&#xf…

java虚拟机参数优化_JAVA虚拟机JVM参数优化(2):垃圾收集算法选择

JAVA虚拟机JVM优化重要性&#xff0c;昨天JAVA虚拟机JVM参数优化(1)文章中已经描述&#xff0c;今天我们来讨论JAVA虚拟机在不同性能要求下如何选择三种垃圾收集算法。JVM内部结构如下图所示&#xff1a;串行收集用于单个线程执行垃圾收集的情况&#xff0c;在这种情况下相对它…

Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)

2019独角兽企业重金招聘Python工程师标准>>> 互联网的发展&#xff0c;网站应用的规模不断扩大&#xff0c;常规的垂直应用架构已无法应对&#xff0c;分布式服务架构以及流动计算架构势在必行&#xff0c;Dubbo是一个分布式服务框架&#xff0c;在这种情况下诞生的…

java clicked_关于java:JComponents在调用mouseClicked()之后消失

我正在用Swing编写Java GUI程序。该界面如下所示&#xff1a;当用户单击右侧的图片之一时&#xff0c;我希望它的一个小的预览显示在左上角的橙色区域中。我通过SwingWorker线程从计算机上的目录中提取所有图像文件。在SwingWorker的done()方法中&#xff0c;我向每个对象添加了…

vim简单命令教程-firstblood

你想以最快的速度学习人类史上最好的文本编辑器VIM吗&#xff1f;你先得懂得如何在VIM幸存下来&#xff0c;然后一点一点地学习各种戏法。 Vim the Six Billion Dollar editor Better, Stronger, Faster. 学习 vim 并且其会成为你最后一个使用的文本编辑器。没有比这个更好的文…

第三课、Qt的诞生和本质------------------狄泰软件学院

一、GUI用户界面元素 &#xff08;1&#xff09;、GUI应用程序是由固定的窗口元素所构成 &#xff08;2&#xff09;、操作系统提供了创建用户界面元素所需要的函数 &#xff08;3&#xff09;、各自功能不同的函数依次调用&#xff0c;从而创建出界面元素 &#xff08;4&#…

Spark RDD算子介绍

Spark学习笔记总结 01. Spark基础 1. 介绍 Spark可以用于批处理、交互式查询&#xff08;Spark SQL&#xff09;、实时流处理&#xff08;Spark Streaming&#xff09;、机器学习&#xff08;Spark MLlib&#xff09;和图计算&#xff08;GraphX&#xff09;。 Spark是MapReduc…

java 写tb级文件_三管齐下!TB 级文件的上传性能瞬间被优化 100 倍!

作者 | 中华石杉责编 | 伍杏玲本文经授权转载石杉的架构笔记(ID&#xff1a;shishan100)这篇文章我们来看看&#xff0c;世界上最优秀的分布式文件系统HDFS&#xff0c;是如何对超大文件的上传做性能优化的&#xff1f;首先&#xff0c;我们还是通过一张图来看一下文件上传的大…

CentOS7下安装Redis — 单节点

2019独角兽企业重金招聘Python工程师标准>>> 1. 环境准备 安装编译所需要的包&#xff1a; yum install gcc tcl 2. 下载redis http://download.redis.io/releases/redis-3.2.7.tar.gz 3. 安装redis ## 创建redis的安装目录 mkdir /usr/local/redis## 解压redis tar…