看过iOS动画之旅的都知道,其中在最后提到一个作者写的开源动画库EasyAnimation(以下简称EA).

EA对CoreAnimation中的view和layer动画做了更高层次的包装和抽象,使得我们可以大大减少编写代码的行数.

不过在玩耍EA时发现了点小问题,在使用链式串行调用中其中的某一段若为弹簧动画,则该动画后面的其他动画都无法再运行了.

以下是测试代码:

@IBAction func actionAddItem(sender: AnyObject) {

    plusButton.enabled = false

    UIView.animateAndChainWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.33, initialSpringVelocity: 0.0, options: [], animations: {
            //1
            self.plusButton.transform = CGAffineTransformRotate(self.plusButton.transform, CGFloat(-M_PI_2))

        }, completion: {_ in
            self.addRandomItem()
    }).animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.33, initialSpringVelocity: 0.0, options: [], animations: {
        //2
        self.plusButton.layer.cornerRadius = 62.5
        self.plusButton.layer.borderWidth = 2.0
        self.plusButton.layer.borderColor = UIColor.grayColor().CGColor
        }, completion: nil).animateWithDuration(0.15, delay: 0.5, options: [.CurveEaseOut,/*.Repeat*/], animations: {
                //3
                self.plusButton.layer.cornerRadius = 0.0
                self.plusButton.layer.borderWidth = 0.0
                self.plusButton.layer.borderColor = UIColor.clearColor().CGColor

            }, completion: {_ in
                self.plusButton.enabled = true
        })

  }

以上我们总共串行执行了3段动画,上面数字注释分别依次指明当前的动画段.

在第一段中我们旋转按钮,在第二段动画中我们修改按钮的边角,边线的样式,在最后一段中我们恢复第二段中做的样式修改.

注意第二段中我们使用了弹簧动画,执行App你会发现第三段动画无法被触发!

cmd+鼠标左键点击第二段中的弹簧动画,我们看一下EA源代码:

public func animateWithDuration(duration: NSTimeInterval, delay: NSTimeInterval, usingSpringWithDamping dampingRatio: CGFloat, initialSpringVelocity velocity: CGFloat, options: UIViewAnimationOptions, animations: () -> Void, completion: ((Bool) -> Void)?) -> EAAnimationDelayed {
        let anim = animateAndChainWithDuration(duration, delay: delay, options: options, animations: animations, completion: completion)
        self.springDamping = dampingRatio
        self.springVelocity = velocity
        return anim
    }

其中返回了另一个EAAnimationDelayed对象,我们再看一下animateAndChainWithDuration这个方法:

public func animateAndChainWithDuration(duration: NSTimeInterval, delay: NSTimeInterval, options: UIViewAnimationOptions, animations: () -> Void, completion: ((Bool) -> Void)?) -> EAAnimationDelayed {
        var options = options

        if options.contains(.Repeat) {
            options.remove(.Repeat)
            loopsChain = true
        }

        self.duration = duration
        self.delay = delay
        self.options = options
        self.animations = animations
        self.completion = completion

        nextDelayedAnimation = EAAnimationDelayed()
        nextDelayedAnimation!.prevDelayedAnimation = self
        return nextDelayedAnimation!
    }

如你所见,该方法只是简单的把CoreAnimation动画中的一些参数放到EAAnimationDelayed对象中来,同时很重要的一步是在方法最后建立EAAnimationDelayed执行链.

我们最后看一下执行链是如何执行的,看一下run方法:

func run() {
        if debug {
            print("run animation #\(debugNumber)")
        }
        //TODO: Check if layer-only animations fire a proper completion block
        if let animations = animations {
            options.insert(.BeginFromCurrentState)
            let animationDelay = dispatch_time(DISPATCH_TIME_NOW, Int64( Double(NSEC_PER_SEC) * self.delay ))

            dispatch_after(animationDelay, dispatch_get_main_queue()) {
                if self.springDamping > 0.0 {
                    //spring animation
                    UIView.animateWithDuration(self.duration, delay: 0, usingSpringWithDamping: self.springDamping, initialSpringVelocity: self.springVelocity, options: self.options, animations: animations, completion: self.animationCompleted)
                } else {
                    //basic animation
                    UIView.animateWithDuration(self.duration, delay: 0, options: self.options, animations: animations, completion: self.animationCompleted)
                }
            }
        }
    }

注意,其中根据springDaming属性的值决定调用何种动画方法!但是在前面EA的animateWithDuration方法中我们赋值的是self的属性,而不是anim的属性!

将EA源代码中上面两句赋值语句修改如下:

anim.springDamping = dampingRatio
anim.springVelocity = velocity

再次运行,可以看到恢复动画可以正常运行了:]

第三方开源动画库EasyAnimation中一个小bug的修复的更多相关文章

  1. Facebook开源动画库 POP-POPBasicAnimation运用

    动画在APP开发过程中还是经常出现,将花几天的时间对Facebook开源动画库 POP进行简单的学习:本文主要针对的是POPBasicAnimation运用:实例源代码已经上传至gitHub,地址:h ...

  2. rebound是facebook的开源动画库

    网址:http://www.jcodecraeer.com/a/opensource/2015/0121/2338.html 介绍: rebound是facebook的开源动画库.可以认为这个动画库是 ...

  3. 关于一个小bug的修正

    python初学者,非常喜欢虫师的文章. 练习时发现一个小bug,http://www.cnblogs.com/fnng/p/3782515.html 验证邮箱格式一题中,第三个x不允许有数字,但是测 ...

  4. iOS开发之使用UICollectionView实现美团App的分类功能【偶现大众点评App的一个小bug】

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...

  5. js动画--一个小bug处理下

    对于上面的课程我们很好的处理了一个小bug,那么我们现在讲程序进行优化一下,前一节的程序中,我们处理处理的属性都是写死了的.为了我们能够很好的对某个属性进行操作的话.我们这样来设置. js文件 win ...

  6. 从一个小Bug,到Azure DevOps

    1. 一个小Bug 最近和同事提起一个几年前的 Bug,那是一个很小很小的 Bug,没什么技术含量.那时候我刚入职,正好公司卖了一款仪器到某个国家,但是那边说配套的软件运行不起来,一打开就报错.经过排 ...

  7. Flutter实战视频-移动电商-34.列表页_小BUG的修复

    34.列表页_小BUG的修复 当高粱酒的子类没有数据返回的时候就会报错. 解决接口空数据报错的问题 没有数据的时候,给用户一个友好的提示, 我们没有数据的时候还要告诉用户,提示一下他没有数据,在我们的 ...

  8. Lottie安卓开源动画库使用

    碉堡的Lottie Airbnb最近开源了一个名叫Lottie的动画库,它能够同时支持iOS,Android与ReactNative的开发.此消息一出,还在苦于探索自定义控件各种炫酷特效的我,兴奋地就 ...

  9. 关于 JavaScript 中一个小细节问题 (在控制台中直接 {Name:'王尼玛',Age:20} 对象报错问题)

    在 Chrome 浏览器,大家可能遇到这样一个小问题. 随便输入一个 Object 对象  ,比如 {Name:'王尼玛',Age:20} ,将会报错.之前,也从来没去考虑过到底是为啥原因. 今天,刚 ...

随机推荐

  1. [LeetCode] Minimum Index Sum of Two Lists 两个表单的最小坐标和

    Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of favorite ...

  2. Linux提示字符设置

    当我们登陆linux后,显示的提示字符究竟是什么意思呢?又可不可以设置呢. 首先来看看默认的显示: 普通用户: [fuwh@localhost ~]$ root用户: [root@localhost ...

  3. ●Joyoi Easy

    题链: http://www.joyoi.cn/problem/tyvj-1952题解: 概率dp (先做的BZOJ 4318: OSU![本人题解],然后就感觉这个题很简单了) 令p[i]表示第i个 ...

  4. jQuery简介和基础

    一.函数变量的作用域 1.变量的作用域实在声明时决定的而不是调用执行时决定 <script> var a=6,b=7; function t() { // var a=3,b=5; con ...

  5. 异步 JavaScript 之 macrotask、microtask

    1.异步任务运行机制 先运行下面的一段代码: console.log('script start'); setTimeout(function() { console.log('setTimeout' ...

  6. 原生js移动端列表无缝间歇向上滚动

    在项目开发中尤其是在项目的活动页面的开发中,经常需要将用户的购买信息或中奖信息等以列表的形式展示在页面当中,并可以使其自动间歇向上滚动来达到在有限的区域内展示所有信息的目的.通常的做法是通过将列表父元 ...

  7. Cannot change version of project facet Dynamic Web Module to 2.5的解决

    步骤1 右键项目 点击Project Facets 修改里面的 Dynamic Web Module 成2.5 maven-update看下有没有解决 步骤2 没有就导入 <dependency ...

  8. 关于一些基础的Java问题的解答(七)

    31. 反射的作用与原理 简单的来说,反射机制其实就是指程序在运行的时候能够获取自身的信息.如果知道一个类的名称或者它的一个实例对象, 就能把这个类的所有方法和变量的信息(方法名,变量名,方法,修饰符 ...

  9. easing--缓动函数--贝塞尔函数--圆盘转动抽奖应用

    http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js http://www.robertpenner.com/easing/penn ...

  10. ionic3-ng4学习见闻--(多环境方案)

    搜了很久,很难找到一个详细入微,开箱即用的方案. 于是我 百折不挠的,搞出来一个,也不知道是不是最完美的方案,有什么可以优化的地方可以指出,谢谢. 首先, 1.项目目录下(与src平级),新增conf ...