IOS动画技术详解

作者: 成功的失败者 | 来源:发表于2016-09-10 22:24 被阅读338次

    视图动画

    UIView动画块

    ios4.0之后在UIView类中提供以下几个处理动画的方法。

    +animateWithDuration:animations
    +animateWithDuration:animations:completion
    +animateWithDuration:delay:options:animations:completion
    

    其中animateWithDuration后面的参数是动画的持续时间。而animations后面是一个block代码块,具体的动画内容就写在这个代码块里面。delay是动画延迟多少时间后执行,如果设置为0就表示马上执行。好啦,接下来我们来看一个例子吧。动画效果如下:


    import UIKit
    
    class AnimationBlokViewController: UIViewController {
        @IBOutlet weak var ball: UIImageView!//关联UIImageView为图片设置动画
        var flag = 1
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
    //为button设置一个点击事件,点击后执行动画
        @IBAction func click(sender: AnyObject) {
            UIView.animateWithDuration(1.5) {
                var frame = self.ball.frame
                frame.origin.y += CGFloat(100 * self.flag)
                self.flag *= -1 
                self.ball.frame = frame
            }
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }
    
    过渡动画

    ios4.o之后在UIView中增加了两个过度动画的方法
    +transitionWithView:duration:options:animations:completion:制定的容器内创建过渡动画。
    +transitionFromView:toView:duration:options:completion:指定的两个视图之间创建过渡动画。
    接下来让我们看看一个例子吧。在视图中创建4个button分别关联下面四个方法。点击就执行对应的过渡动画。值得注意的是其中options参数含有多个值时在oc中是按位或符号|将多个参数连接起来,而在swift中会报错,在swift中我们使用传递数组的形式[]传递多个参数。
    相关的options参数有:
    1.TransitionFlipLeft:从左往右翻转
    2.TransitionFlipRight:从右往左翻转
    3.TransitionCurlUp:向上翻页
    4.TransitionCurlDown:向下翻页
    5.TransitionCrossDissolve:交叉溶解效果
    6.TransitionFlipFromTop:从上往下翻转
    7.TransitionFlipFromBottom:从下往上翻转
    8.CurveEaseInOut:缓入缓出,开始和结束时减速
    9.CurveEaseIn:缓入,开始时减速
    10.CurveEaseOut:缓出,结束时减速
    11.CurveEaseLinear:线性,匀速运动
    其中前七个或者后四个不能同时有两个或者以上在一个数组中使用否则会冲突。
    动画效果如下:


    collision.gif
    import UIKit
    
    class UICollisonViewController: UIViewController {
        @IBOutlet weak var ballImageView: UIImageView!
        
        var collision : UICollisionBehavior!
        var animator : UIDynamicAnimator!
        var gravity : UIGravityBehavior!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.title = "碰撞行为"
        }
    
        override func viewDidAppear(animated: Bool) {
            super.viewDidAppear(animated)
            self.animator = UIDynamicAnimator(referenceView: self.view)
            //重力行为
            self.gravity = UIGravityBehavior(items: [self.ballImageView])
            let gravityDirection : CGVector = CGVectorMake(0.0, 0.1)
            self.gravity.gravityDirection = gravityDirection
            self.animator.addBehavior(self.gravity)
            //碰撞行为
            self.collision = UICollisionBehavior(items: [self.ballImageView])
            self.collision.translatesReferenceBoundsIntoBoundary = true
            self.animator.addBehavior(self.collision)
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }```
    #####3.吸附行为(UIAttachmentBehavior)
    吸附行为可以实现两个物体彼此牵制,就好像用一根棍子将两个物体连接在一起。效果图如下:
    
    ![attachment.gif](http:https://img.haomeiwen.com/i1746439/6d3bd327c889af58.gif?imageMogr2/auto-orient/strip)
    
    

    import UIKit

    class UIAttachmentViewController: UIViewController,UICollisionBehaviorDelegate {

    @IBOutlet weak var attachmentPoint: UIImageView!
    @IBOutlet weak var box: UIImageView!
    @IBOutlet weak var barrier: UIImageView!
    var collision : UICollisionBehavior!
    var animator : UIDynamicAnimator!
    var gravity : UIGravityBehavior!
    var attach : UIAttachmentBehavior!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "吸附行为"
    }
    
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        self.animator = UIDynamicAnimator(referenceView: self.view)
        //重力行为
        self.gravity = UIGravityBehavior(items: [self.box])
        self.animator.addBehavior(self.gravity)
        //碰撞行为
        self.collision = UICollisionBehavior(items: [self.box])
        let width = self.barrier.frame.size.width
        let origin = self.barrier.frame.origin
        self.collision.addBoundaryWithIdentifier("barrier", fromPoint: origin, toPoint: CGPointMake(origin.x+width, origin.y))
        self.collision.translatesReferenceBoundsIntoBoundary = true
        self.collision.collisionDelegate = self
        self.animator.addBehavior(self.collision)
        let itemBehaviour = UIDynamicItemBehavior(items: [self.box])
        itemBehaviour.elasticity = 0.5
        self.animator.addBehavior(itemBehaviour)
    }
    //碰撞行为协议
    internal func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, atPoint p: CGPoint){
        //吸附行为
        self.attach = UIAttachmentBehavior(item: self.attachmentPoint, attachedToItem: self.box)
        self.animator.addBehavior(self.attach)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    

    }```

    4.推行为(UIPushBehavior)

    推行为可以使视图对象朝某个方向运动,这个推力有瞬间(UIPushBehaviorModeInstantaneous)(UIPushBehaviorModeContinuous)两种。效果图如下:

    push.gif
    import UIKit
    
    class UIPushViewController: UIViewController,UICollisionBehaviorDelegate {
    
        @IBOutlet weak var barrier: UIImageView!
        @IBOutlet weak var box: UIImageView!
        @IBOutlet weak var attachmentPoint: UIImageView!
        var firstConcact = false
        
        var collision : UICollisionBehavior!
        var animator : UIDynamicAnimator!
        var gravity : UIGravityBehavior!
        var attach : UIAttachmentBehavior!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            self.title = "推行为"
        }
        
        override func viewDidAppear(animated: Bool) {
            super.viewDidAppear(animated)
            self.animator = UIDynamicAnimator(referenceView: self.view)
            self.gravity = UIGravityBehavior(items: [self.box])
            self.animator.addBehavior(self.gravity)
            
            self.collision = UICollisionBehavior(items: [self.box])
            let width = self.barrier.frame.size.width
            let origin = self.barrier.frame.origin
            self.collision.addBoundaryWithIdentifier("barrier", fromPoint: origin, toPoint: CGPointMake(origin.x+width, origin.y))
            self.collision.translatesReferenceBoundsIntoBoundary = true
            self.collision.collisionDelegate = self
            self.animator.addBehavior(self.collision)
            let itemBehaviour = UIDynamicItemBehavior(items: [self.box])
            itemBehaviour.elasticity = 0.5
            self.animator.addBehavior(itemBehaviour)
        }
        
        internal func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, atPoint p: CGPoint){
            if !self.firstConcact {
            self.firstConcact = true
            
            self.attach = UIAttachmentBehavior(item: self.attachmentPoint, attachedToItem: self.box)
            self.animator.addBehavior(self.attach)
            //设置推行为
            let push = UIPushBehavior(items: [self.box],mode: UIPushBehaviorMode.Instantaneous)
            //设置推行为的方向和力度
            push.setAngle(CGFloat(-M_PI/4.0), magnitude: 5.0)
            self.animator.addBehavior(push)
            
            }
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }```
    #####5.甩行为(UISnapBehavior)
    能够使物体朝某个方向甩出,并有瞬间加速度,由慢及快,再由快及慢,最后停止在目标点。效果图如下:
    
    ![snap.gif](http:https://img.haomeiwen.com/i1746439/741dc692417379f9.gif?imageMogr2/auto-orient/strip)
    
    

    import UIKit

    class UISnapViewController: UIViewController {
    var animator : UIDynamicAnimator!
    var snap : UISnapBehavior!

    @IBOutlet weak var box: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        box.userInteractionEnabled = true;
        box.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(UISnapViewController.snapClick(_:))))
          self.title = "甩行为"
    }
    
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        self.animator = UIDynamicAnimator(referenceView: self.view)
       
    }
    

    func snapClick(sender: AnyObject) {
    print("甩")
    let gesture = sender as! UITapGestureRecognizer
    let point = gesture.locationInView(self.view)
    if self.snap != nil {
    self.animator.removeBehavior(self.snap)
    }
    self.snap = UISnapBehavior(item: self.box, snapToPoint: point)
    self.animator.addBehavior(self.snap)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    

    }```

    6.行为限制(DynamicItemBehavior)

    行为限制于上面五个行为不同,它是用来设置力学行为参数的。参数如下:
    (1)density:密度,如果一个100x100点的物体密度是1.0作用力是1.0那么它的加速度是100点/s^2
    (2)elasity:弹性系数,取值范围0.0-1.0。其中0.0代表没有反弹,1.0代表完全弹性碰撞。
    (3)friction:摩擦系数,0.0表示没有摩擦力,1.0表示摩擦力很强。还可以设置超过1.0的跟大的摩擦力。
    (4)resistance:阻力,0.0表示没有阻力,CGFLOAT_MAX表示最大阻力。
    (5)allowsRotation:是否允许旋转。
    (6)angularResistance:角阻力,物体旋转是旋转方向的阻力。
    我们来看看DynamicItemBehavior具体怎么使用吧:

     let itemBehaviour = UIDynamicItemBehavior(items:[self.view])
            itemBehaviour.elasticity = 0.5
            itemBehaviour.allowsRotation = true
            itemBehaviour.friction = 0.0
            itemBehaviour.resistance = 0.0
            self.animator.addBehavior(itemBehaviour)
    

    Core Animation框架

    (1)隐式动画是一种最简单动画,不用设置定时器,不用考虑线程或者重画,它的很多属性都是默认的。
    (2)显式动画是一种使用CABasicAnimation创建的动画通过CABasicAnimation,可以更明确的定义属性如何改变动画。
    动画效果如下:


    隐式动画
    import UIKit
    
    class ExplicitViewController: UIViewController {
        @IBOutlet weak var plane: UIImageView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.plane.layer.opacity = 0.25
        }
    
        //不透明度从0.25-1.0
        @IBAction func implicitClick(sender: AnyObject) {
            let moveTransform = CGAffineTransformMakeTranslation(180, 200)
            self.plane.layer.setAffineTransform(moveTransform)
            self.plane.layer.opacity = 1;
        }
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }```
    #####显式动画
    

    import UIKit

    class ExplicitViewController: UIViewController {
    @IBOutlet weak var plane: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.plane.layer.opacity = 0.25
    }
    

    @IBAction func explicitClick(sender: AnyObject) {
    let opAnim = CABasicAnimation(keyPath: "opacity")
    //定义动画时间
    opAnim.duration = 3.0
    //将透明的从0.25-1.0
    opAnim.fromValue = 0.25
    opAnim.toValue = 1.0
    //指定累计上次值
    opAnim.cumulative = true
    //动画重复2次
    opAnim.repeatCount = 2
    //保持动画结束值
    opAnim.fillMode = kCAFillModeForwards
    //动画结束时不停止
    opAnim.removedOnCompletion = false
    self.plane.layer.addAnimation(opAnim, forKey: "animateOpacity")

        let moveTransform = CGAffineTransformMakeTranslation(180, 200)
        let moveAnim = CABasicAnimation(keyPath: "transform")
        moveAnim.duration = 6.0
        moveAnim.toValue = NSValue(CATransform3D: CATransform3DMakeAffineTransform(moveTransform))
        moveAnim.fillMode = kCAFillModeForwards
        moveAnim.removedOnCompletion = false
        self.plane.layer.addAnimation(moveAnim, forKey: "animateTransform")
        opAnim.fillMode = kCAFillModeForwards
        opAnim.removedOnCompletion = false
        
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    

    }```

    关键帧动画
    import UIKit
    
    class ExplicitViewController: UIViewController {
        @IBOutlet weak var plane: UIImageView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.plane.layer.opacity = 0.25
        }
    
     @IBAction func keyFrameClick(sender: AnyObject) {
            let opAnim = CAKeyframeAnimation(keyPath: "opacity")
            opAnim.duration = 6.0
            opAnim.values = [0.25,0.75,1.0]
            opAnim.keyTimes = [0.0,0.5,1.0]
            opAnim.fillMode = kCAFillModeForwards
            opAnim.removedOnCompletion = false
            self.plane.layer.addAnimation(opAnim, forKey: "animateOpacity")
            
            let moveTransform = CGAffineTransformMakeTranslation(180, 200)
            let moveAnim = CABasicAnimation(keyPath: "transform")
            moveAnim.duration = 6.0
            moveAnim.toValue = NSValue(CATransform3D: CATransform3DMakeAffineTransform(moveTransform))
            moveAnim.fillMode = kCAFillModeForwards
            moveAnim.removedOnCompletion = false
            self.plane.layer.addAnimation(moveAnim, forKey: "animateTransform")
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }```
    #####使用路径
    效果图如下:
    
    ![usePath.gif](http:https://img.haomeiwen.com/i1746439/bdfb4ecc4f660fe4.gif?imageMogr2/auto-orient/strip)
    
    

    import UIKit

    class PathViewController: UIViewController {
    @IBOutlet weak var ball: UIImageView!
    var flag = 1
    @IBOutlet weak var button: UIButton!
    override func viewDidLoad() {
    super.viewDidLoad()
    }

    @IBAction func click(sender: AnyObject) {
        self.button.alpha = 0.0
        //创建可变路径
        let startPath = CGPathCreateMutable()
        CGPathMoveToPoint(startPath, nil, 160.0, 100.0)
        CGPathAddLineToPoint(startPath, nil, 100.0, 280.0)
        CGPathAddLineToPoint(startPath, nil, 260.0, 170.0)
         CGPathAddLineToPoint(startPath, nil, 60.0, 170.0)
        CGPathAddLineToPoint(startPath, nil, 220.0, 280.0)
         //封闭子路径
        CGPathCloseSubpath(startPath)
        
        let animation = CAKeyframeAnimation(keyPath: "position")
        animation.duration = 5.0
         //只有关键帧动画才有setPath方法
        animation.path = startPath
        animation.delegate = self
        self.ball.layer.addAnimation(animation, forKey: "position")
    
    }
    
    override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
        UIView.animateWithDuration(1.0) {
            self.button.alpha = 1.0
        }
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    

    }

    所有的代码实例我都建在一个git工程里面,https://git.oschina.net/2276282419/Animator需要的朋友可以下载源代码看看。

    相关文章

      网友评论

      本文标题:IOS动画技术详解

      本文链接:https://www.haomeiwen.com/subject/hroyettx.html