zoukankan      html  css  js  c++  java
  • 用 Swift 语言写一个地图坐标弹跳动画

    上次写了《用 Swift 语言写一个地图坐标弹跳动画》,有位仁兄默默地在下面踩了一下,看样子是觉得写的不好。

    当然写的不好!

    我们再来理理,iOS动画大概分这几种:

    1. CoreAnimation动画(基础)
    2. UIView动画(animateWithDuration开头的函数,带弹簧特效)
    3. UIDynamic动画(有物理引擎)

    上次写弹跳动画,由于刚开始学,就用了最基础的CA动画,但是因为自己不会写KeyFrame,所以还引用了一个开源库来实现下坠的弹跳效果,这样固然是实现了需求,但是一点都不优雅——从iOS7开始,有了2、3两种动画,就不再需要用老的CA动画去一点一点拔了。做这个动画的正确姿势,应该是下面这样~

    我们的需求仍然是这个弹跳的marker:

    这次我用了2、3两种方式实现,效果如下:

    一、UIView动画

    之前使用CABasicAnimation实现,不仅代码多,还要用CATransaction控制回来的一趟callback。其实直接用iOS7的UIView动画就搞定了:

    UIView.animateWithDuration(0.2, animations: {
        self.marker.layer.position.y -= 30
        }, completion: {(finished) in
            UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 5.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {//弹性参数的调教,可以参见本文的“参考”部分
                self.marker.layer.position.y += 30
                }, completion: nil)
    })

    在上升过程中,直接在0.2s的时间中,向上移动30px;向下过程中,为了表示弹跳的效果,使用了Spring系列参数,做了一下调整之后,感觉效果还是挺有意思的。但是单纯使用这个有一个缺点:我们要的是类似于重力下坠,而非像一根弹簧一样弹到那个位置。注意那跟蓝色的比较线,我们实现的是左边的效果,在动画过程中,它会超过那根蓝色线条,所以其实是不符合需求的。

    二、UIDynamic动画

    UIDynamic动画是有物理引擎的动画,我们只需要设定这个“物体”的物理特性,iOS就会自动帮我们进行物理世界的动画运算。首先我们创建它的物理特性:

    var animator : UIDynamicAnimator?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        animator = UIDynamicAnimator(referenceView: view)
    }
    
    override func viewDidAppear(animated: Bool) {
        let gravity = UIGravityBehavior(items: [marker2])//重力
        let elastic = UIDynamicItemBehavior(items: [marker2])//弹性
        elastic.elasticity = 0.6
        let collision = UICollisionBehavior(items: [marker2])//边缘
        let endY = marker2.frame.origin.y + marker2.frame.height//记录marker2的底部坐标
        collision.addBoundaryWithIdentifier("floor", fromPoint: CGPoint(x: 0, y: endY), toPoint: CGPoint(x: UIScreen.mainScreen().bounds.width, y: endY))//在marker2的底部画一条线,从屏幕左边到屏幕右边
        
        animator!.addBehavior(collision)
        animator!.addBehavior(gravity)
        animator!.addBehavior(elastic)
    }

    首先我们创建一个animator,然后创建关于marker2的重力、弹性、边缘三个属性,附加在animator上。于是这个marker2便有了物理特性。然后我们和以前一样把它抬高:

    UIView.animateWithDuration(0.2, animations: {
        self.marker2.layer.position.y -= 30
        }, completion: {(finished : Bool) in
            self.animator!.updateItemUsingCurrentState(self.marker2)//如果不update,则animator不知道它的位置被移动过了
    })

    在动画完成后,让animator重新对它进行活动,就达到了文章开始的gif图中,第二个marker的弹跳效果。

    参考

    WWDC 2013 Session笔记 - UIKit Dynamics入门:
    http://onevcat.com/2013/06/uikit-dynamics-started/
    UIKit Dynamics Tutorial:
    http://www.raywenderlich.com/50197/uikit-dynamics-tutorial
    iOS 8 Spring Animation:
    http://www.tuicool.com/articles/ZR7nYv

  • 相关阅读:
    1039 到底买不买 (20分)
    流密码
    Socket网络编程:互相通讯
    1036 跟奥巴马一起编程
    1033 旧键盘打字
    1029 旧键盘
    1015 德才论 (25分)
    BUU_Real_刷题记录
    vue3 composition api 对比 react hooks
    vue3 文档相关
  • 原文地址:https://www.cnblogs.com/missingcat92/p/4673267.html
Copyright © 2011-2022 走看看