iOS 动画Animation - 6 - 3 实战练习之复杂动画拆装

其实我们在看到的每一个复杂的动画都是有许多简单的动画巧妙的拼装出来的,在教给大家学会拼装一个动画,其实我更愿意教会大家如何去拆解一个动画。如果看到一个动画,会去把它拆解成一个个简单的动画,那么实现这个动画就轻而易举了。

先给大家看一张效果图:

动画分析

这个动画其实在实现的时候并不困难,可能很多人怕就怕在没有思路,下面我就将这个动画拆解。

  • 1、先出来一个圆,圆形在水平和竖直方向上被挤压,呈椭圆形状的一个过程,最后恢复成圆形
  • 2、圆形的左下角、右下角和顶部分别按顺序凸出一小部分
  • 3、圆和凸出部分形成的图形旋转一圈后变成三角形
  • 4、三角形的左边先后出来两条宽线,将三角形围在一个矩形中
  • 5、矩形由底部向上被波浪状填满
  • 6、被填满的矩形放大至全屏

动画实现

  • 1、先出来一个圆,并实现横向和竖向挤压的效果
    func addCircle() {

        shapeLayer.frame = CGRect(x: screenWidth/2 - 50, y: screenHeight/2 - 50, width: 100, height: 100)
        shapeLayer.fillColor = UIColor.orangeColor().CGColor
        view.layer.addSublayer(shapeLayer)
        // 画小圆
        let path1 = UIBezierPath(ovalInRect: CGRect(x: 40, y: 40, width: 20, height: 20))
        // 变成大圆
        let path2 = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: 100, height: 100))
        // 横向挤压
        let path3 = UIBezierPath(ovalInRect: CGRect(x: 5, y: 0, width: 90, height: 100))
        // 恢复
        let path4 = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: 100, height: 100))
        // 竖向挤压
        let path5 = UIBezierPath(ovalInRect: CGRect(x: 0, y: 5, width: 100, height: 90))
        // 恢复
        let path6 = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: 100, height: 100))
        let animation = CAKeyframeAnimation(keyPath: "path")
        animation.values = [path1.CGPath, path2.CGPath, path3.CGPath, path4.CGPath, path5.CGPath, path6.CGPath, path3.CGPath, path4.CGPath, path5.CGPath, path6.CGPath];
        animation.duration = 1
        animation.beginTime = 0
        animation.removedOnCompletion = false
        animation.fillMode = kCAFillModeForwards
        shapeLayer.addAnimation(animation, forKey: nil)

    }

里面的内容我就不再多做介绍了,这些都是简单的动画,如果不够了解,请看本专题之前的文章

实现效果如下图:

  • 2、圆形的左下角、右下角和顶部分别按顺序凸出一小部分

看似是圆的周围一次多出来一个角,实际行就是一个颜色与圆相同的三角在做变化,这个动画跟圆没有关系。如果我将这个三角换一种颜色,并且将动画放慢,就是这样的

看代码:


    func addSanjiao() {

        shapeLayer1.frame = CGRect(x: screenWidth/2 - 50, y: screenHeight/2 - 50, width: 100, height: 100)
        shapeLayer1.strokeColor = UIColor.orangeColor().CGColor
        shapeLayer1.fillColor = UIColor.orangeColor().CGColor
        shapeLayer1.lineJoin = kCALineJoinRound
        shapeLayer1.lineWidth = 10
        view.layer.addSublayer(shapeLayer1)
        // 画一个三角,一定要小于圆
        let path11 = UIBezierPath()
        path11.moveToPoint(CGPoint(x: 50, y: 10))
        path11.addLineToPoint(CGPoint(x: 15, y: 75))
        path11.addLineToPoint(CGPoint(x: 85, y: 75))
        path11.closePath()
        // 改变三角左下角的位置
        let path12 = UIBezierPath()
        path12.moveToPoint(CGPoint(x: 50, y: 10))
        path12.addLineToPoint(CGPoint(x: -5, y: 75))
        path12.addLineToPoint(CGPoint(x: 85, y: 75))
        path12.closePath()
        // 改变三角右下角的位置
        let path13 = UIBezierPath()
        path13.moveToPoint(CGPoint(x: 50, y: 10))
        path13.addLineToPoint(CGPoint(x: -5, y: 75))
        path13.addLineToPoint(CGPoint(x: 105, y: 75))
        path13.closePath()
        // 改变三角顶角的位置
        let path14 = UIBezierPath()
        path14.moveToPoint(CGPoint(x: 50, y: -10))
        path14.addLineToPoint(CGPoint(x: -5, y: 75))
        path14.addLineToPoint(CGPoint(x: 105, y: 75))
        path14.closePath()

        let animation1 = CAKeyframeAnimation(keyPath: "path")
        animation1.values = [path11.CGPath, path12.CGPath, path13.CGPath, path14.CGPath];
        animation1.duration = 0.25
        animation1.removedOnCompletion = false
        animation1.fillMode = kCAFillModeForwards
        shapeLayer1.addAnimation(animation1, forKey: nil)

    }
  • 3、圆和凸出部分形成的图形旋转一圈后变成三角形

    这个其实只是让三角旋转就好了,因为圆的旋转看不出来的O(∩_∩)O~~,然后圆做缩小动画,同样将动画放慢,效果如下:

三角画的有点不规整啊,转起来有点丑,请忽略细节(* ^__^*)

实现代码如下:

    func xuanzhuan() {
        // 三角旋转
        let animation = CAKeyframeAnimation(keyPath: "transform.rotation")
        animation.duration = 0.5
        animation.values = [0, M_PI * 2]
        shapeLayer1.addAnimation(animation, forKey: nil)
        // 圆缩小
        let animation1 = CAKeyframeAnimation(keyPath: "transform.scale")
        animation1.duration = 1
        animation1.values = [1, 0]
        animation1.removedOnCompletion = false
        animation1.fillMode = kCAFillModeForwards
        shapeLayer.addAnimation(animation1, forKey: nil)

    }
  • 4、三角形的左边先后出来两条宽线,将三角形围在一个矩形中

    这部分相对来说就更简单了, 就是画一矩形

代码如下:

    func rectAngle() {
        let shapeLayer2 = CAShapeLayer()
        shapeLayer2.frame = CGRect(x: screenWidth/2 - 60, y: screenHeight/2 - 90, width: 120, height: 120)
        view.layer.addSublayer(shapeLayer2)
        let path21 = UIBezierPath(rect:  CGRect(x: 0, y: 0, width: 120, height: 120))
        shapeLayer2.transform = CATransform3DMakeRotation(CGFloat(-M_PI), 0, 0, 1)
        shapeLayer2.path = path21.CGPath
        shapeLayer2.strokeStart = 0
        shapeLayer2.lineWidth = 5
        shapeLayer2.strokeColor = UIColor.cyanColor().CGColor
        shapeLayer2.fillColor = UIColor.clearColor().CGColor
        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.duration = 0.5
        animation.fromValue = 0
        animation.toValue = 1
        shapeLayer2.addAnimation(animation, forKey: nil)
    }
  • 5、矩形由底部向上被波浪状填满

    波浪线就是二次贝塞尔曲线在不停的变换,我画的有点多了,其实可以省点画

    同样将动画放慢

    func waves() {
        let shapeLayer3 = CAShapeLayer()
        shapeLayer3.frame = CGRect(x: screenWidth/2 - 60, y: screenHeight/2 - 90, width: 120, height: 120)
        shapeLayer3.fillColor = UIColor.cyanColor().CGColor
        view.layer.addSublayer(shapeLayer3)
        let path31 = UIBezierPath()
        path31.moveToPoint(CGPoint(x: 0, y: 100))
        path31.addCurveToPoint(CGPoint(x: 120, y: 100), controlPoint1: CGPoint(x: 40, y: 80), controlPoint2: CGPoint(x: 80, y: 120))
        path31.addLineToPoint(CGPoint(x: 120, y: 120))
        path31.addLineToPoint(CGPoint(x: 0, y: 120))
        path31.closePath()
        let path32 = UIBezierPath()
        path32.moveToPoint(CGPoint(x: 0, y: 80))
        path32.addCurveToPoint(CGPoint(x: 120, y: 80), controlPoint1: CGPoint(x: 40, y: 100), controlPoint2: CGPoint(x: 80, y: 60))
        path32.addLineToPoint(CGPoint(x: 120, y: 120))
        path32.addLineToPoint(CGPoint(x: 0, y: 120))
        path32.closePath()
        let path33 = UIBezierPath()
        path33.moveToPoint(CGPoint(x: 0, y: 60))
        path33.addCurveToPoint(CGPoint(x: 120, y: 60), controlPoint1: CGPoint(x: 40, y: 40), controlPoint2: CGPoint(x: 80, y: 80))
        path33.addLineToPoint(CGPoint(x: 120, y: 120))
        path33.addLineToPoint(CGPoint(x: 0, y: 120))
        path33.closePath()
        let path34 = UIBezierPath()
        path34.moveToPoint(CGPoint(x: 0, y: 40))
        path34.addCurveToPoint(CGPoint(x: 120, y: 40), controlPoint1: CGPoint(x: 40, y: 60), controlPoint2: CGPoint(x: 80, y: 20))
        path34.addLineToPoint(CGPoint(x: 120, y: 120))
        path34.addLineToPoint(CGPoint(x: 0, y: 120))
        path34.closePath()
        let path35 = UIBezierPath()
        path35.moveToPoint(CGPoint(x: 0, y: 20))
        path35.addCurveToPoint(CGPoint(x: 120, y: 20), controlPoint1: CGPoint(x: 40, y: 0), controlPoint2: CGPoint(x: 80, y: 40))
        path35.addLineToPoint(CGPoint(x: 120, y: 120))
        path35.addLineToPoint(CGPoint(x: 0, y: 120))
        path35.closePath()
        let path36 = UIBezierPath()
        path36.moveToPoint(CGPoint(x: 0, y: 0))
        path36.addCurveToPoint(CGPoint(x: 120, y: 0), controlPoint1: CGPoint(x: 40, y: 0), controlPoint2: CGPoint(x: 80, y: 0))
        path36.addLineToPoint(CGPoint(x: 120, y: 120))
        path36.addLineToPoint(CGPoint(x: 0, y: 120))
        path36.closePath()
        let animation1 = CAKeyframeAnimation(keyPath: "path")
        animation1.values = [path31.CGPath, path32.CGPath, path33.CGPath, path34.CGPath, path35.CGPath, path36.CGPath];
        animation1.duration = 0.5
        animation1.removedOnCompletion = false
        animation1.fillMode = kCAFillModeForwards
        shapeLayer3.addAnimation(animation1, forKey: nil)

    }

都是重复的内容,我也不想说啥

  • 6、被填满的矩形放大至全屏

在来个放大到全屏的动画,整个动画就ok了

    func fullScreen() {
        let someView = UIView()
        someView.frame = CGRect(x: screenWidth/2 - 60, y: screenHeight/2 - 90, width: 120, height: 120)
        view.addSubview(someView)
        someView.backgroundColor = UIColor.cyanColor()
        UIView.animateWithDuration(0.25) {
            someView.frame = CGRect(x: 0, y: 0, width: self.screenWidth, height: self.screenHeight)
        }
    }

结束语:

其实单从每一步来讲,每个动画都不困难,重要的是要能想到这么做。这里有做好的demo可以参考一下

时间: 2024-10-21 08:56:46

iOS 动画Animation - 6 - 3 实战练习之复杂动画拆装的相关文章

iOS Core Animation Advanced Techniques(四):隐式动画和显式动画

隐式动画 按照我的意思去做,而不是我说的. -- 埃德娜,辛普森 我们在第一部分讨论了Core Animation除了动画之外可以做到的任何事情.但是动画师Core Animation库一个非常显著的特性.这一章我们来看看它是怎么做到的.具体来说,我们先来讨论框架自动完成的隐式动画(除非你明确禁用了这个功能). 事务 Core Animation基于一个假设,说屏幕上的任何东西都可以(或者可能)做动画.动画并不需要你在Core Animation中手动打开,相反需要明确地关闭,否则他会一直存在.

iOS中Animation 动画 UI_22

1.iOS中我们能看到的控件都是UIView的子类,比如UIButton UILabel UITextField UIImageView等等 2.UIView能够在屏幕的显示是因为在创建它的时候内部自动添加一个CALayer图层,通过这个图层在屏幕上显示的时候会调用一个drawRect: 的方法,完成绘图,才能在屏幕上显示 3.CALayer 本身就具有显示功能,但是它不能响应用户的交互事件,如果只是单纯的显示一个图形,此时你可以使用CALayer创建或者是使用UIView创建,但是如果这个图形

蓝懿 iOS 动画Animation

iOS Animation详解 本篇只要讲解iOS中动画的使用. Animtion主要分为两类:UIView动画和CoreAnimation动画. UIView动画有UIView属性动画,UIViewBlock动画,UIViewTransition动画. 而CoreAnimation动画主要通过CAAnimation和CALayer,常用的有CABasicAnimation,CAKeyframeAnimation,CATransition,CAAnimationGroup. UIView动画 U

IOS-动画Animation

iOS Animation详解 本篇只要讲解iOS中动画的使用. Animtion主要分为两类:UIView动画和CoreAnimation动画. UIView动画有UIView属性动画,UIViewBlock动画,UIViewTransition动画. 而CoreAnimation动画主要通过CAAnimation和CALayer,常用的有CABasicAnimation,CAKeyframeAnimation,CATransition,CAAnimationGroup. UIView动画 U

转 iOS Core Animation 动画 入门学习(一)基础

iOS Core Animation 动画 入门学习(一)基础 reference:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004514 在iOS中,每个view中都自动配置了一个layer,我们不能人为新建,而在Mac OS中,view默认是没有

iOS Core Animation Advanced Techniques(六): 基于定时器的动画和性能调优

基于定时器的动画 我可以指导你,但是你必须按照我说的做. -- 骇客帝国 在第10章“缓冲”中,我们研究了CAMediaTimingFunction,它是一个通过控制动画缓冲来模拟物理效果例如加速或者减速来增强现实感的东西,那么如果想更加真实地模拟 物理交互或者实时根据用户输入修改动画改怎么办呢?在这一章中,我们将继续探索一种能够允许我们精确地控制一帧一帧展示的基于定时器的动画. 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显

iOS Core Animation Advanced Techniques-隐式动画

上六章节: 图层树 图层的寄宿图 图层几何学 图层视觉效果 图层变换 专用图层 这篇随笔主要介绍有关图层隐式动画. 隐式动画: 没有指定任何动画类型,而改变了一个属性,Core Animation决定如何并且何时去做动画. 动画执行的事件取决于当前事务的设置: 动画类型取决于图层行为. Core Animation假设屏幕上任何东西都可能做动画,默认动画效果是打开的. 当CALayer的一个 可做动画的 属性 被改变,默认从先前值平滑过渡到新值,而不是立刻显示新值在屏幕上,因此携带了隐式动画.

iOS Core Animation Advanced Techniques-显式动画

上七章节: 图层树 图层的寄宿图 图层几何学 图层视觉效果 图层变换 专用图层 隐式动画 这篇随笔主要介绍有关图层显式动画. 显示动画: 能对一些属性做指定的自定义动画,或者创建非线性动画 属性动画: 属性动画作用于图层的某个单一属性,并指定了它的一个目标值,或一连串将要做动画的值 属性动画分两种: 1.基础 2.关键帧 基础动画:(通过CALayer的实例方法addAnimation: forKey:给图层添加显示动画) CABasicAnimation-->CAPropertyAnimati

iOS Core Animation学习总结(3)--动画的基本类型

一. CABasicAnimation (基础动画) 移位: CABasicAnimation *animation = [CABasicAnimation animation]; //keyPath指定动画类别,position表示移位 animation.keyPath = @"position"; //移动到x=200,y=200的位置 animation.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)]; an