Swift-EasingAnimation

Swift-EasingAnimation

 

效果

 http://gizma.com/easing/

 

源码

https://github.com/YouXianMing/UI-Component-Collection


//
//  Easing.swift
//  Swift-EasingAnimation
//
//  Created by YouXianMing on 15/10/21.
//
//  https://github.com/YouXianMing
//  http://home.cnblogs.com/u/YouXianMing/
//

import UIKit

enum EasingFunction: Int {
    
    case
    LinearInterpolation = 1,
    
    // Quadratic easing; p^2
    QuadraticEaseIn,
    QuadraticEaseOut,
    QuadraticEaseInOut,
    
    // Cubic easing; p^3
    CubicEaseIn,
    CubicEaseOut,
    CubicEaseInOut,
    
    // Quartic easing; p^4
    QuarticEaseIn,
    QuarticEaseOut,
    QuarticEaseInOut,
    
    // Quintic easing; p^5
    QuinticEaseIn,
    QuinticEaseOut,
    QuinticEaseInOut,
    
    // Sine wave easing; sin(p * PI/2)
    SineEaseIn,
    SineEaseOut,
    SineEaseInOut,
    
    // Circular easing; sqrt(1 - p^2)
    CircularEaseIn,
    CircularEaseOut,
    CircularEaseInOut,
    
    // Exponential easing, base 2
    ExponentialEaseIn,
    ExponentialEaseOut,
    ExponentialEaseInOut,
    
    // Exponentially-damped sine wave easing
    ElasticEaseIn,
    ElasticEaseOut,
    ElasticEaseInOut,
    
    // Overshooting cubic easing;
    BackEaseIn,
    BackEaseOut,
    BackEaseInOut,
    
    // Exponentially-decaying bounce easing
    BounceEaseIn,
    BounceEaseOut,
    BounceEaseInOut
    
    func value() -> ((Double) -> Double) {
        
        switch self {
            
        case .LinearInterpolation:
            return Easing.LinearInterpolation
            
        case .QuadraticEaseIn:
            return Easing.QuadraticEaseIn
            
        case .QuadraticEaseOut:
            return Easing.QuadraticEaseOut
            
        case .QuadraticEaseInOut:
            return Easing.QuadraticEaseInOut
            
        case .CubicEaseIn:
            return Easing.CubicEaseIn
            
        case .CubicEaseOut:
            return Easing.CubicEaseOut
            
        case .CubicEaseInOut:
            return Easing.CubicEaseInOut
            
        case .QuarticEaseIn:
            return Easing.QuarticEaseIn
            
        case .QuarticEaseOut:
            return Easing.QuarticEaseOut
            
        case .QuarticEaseInOut:
            return Easing.QuarticEaseInOut
            
        case .QuinticEaseIn:
            return Easing.QuinticEaseIn
            
        case .QuinticEaseOut:
            return Easing.QuinticEaseOut
            
        case .QuinticEaseInOut:
            return Easing.QuinticEaseInOut
            
        case .SineEaseIn:
            return Easing.SineEaseIn
            
        case .SineEaseOut:
            return Easing.SineEaseOut
            
        case .SineEaseInOut:
            return Easing.SineEaseInOut
            
        case .CircularEaseIn:
            return Easing.CircularEaseIn
            
        case .CircularEaseOut:
            return Easing.CircularEaseOut
            
        case .CircularEaseInOut:
            return Easing.CircularEaseInOut
            
        case .ExponentialEaseIn:
            return Easing.ExponentialEaseIn
            
        case .ExponentialEaseOut:
            return Easing.ExponentialEaseOut
            
        case .ExponentialEaseInOut:
            return Easing.ExponentialEaseInOut
            
        case .ElasticEaseIn:
            return Easing.ElasticEaseIn
            
        case .ElasticEaseOut:
            return Easing.ElasticEaseOut
            
        case .ElasticEaseInOut:
            return Easing.ElasticEaseInOut
            
        case .BackEaseIn:
            return Easing.BackEaseIn
            
        case .BackEaseOut:
            return Easing.BackEaseOut
            
        case .BackEaseInOut:
            return Easing.BackEaseInOut
            
        case .BounceEaseIn:
            return Easing.BounceEaseIn
            
        case .BounceEaseOut:
            return Easing.BounceEaseOut
            
        case .BounceEaseInOut:
            return Easing.BounceEaseInOut
        }
    }
}

class Easing: NSObject {

    // MARK: Linear interpolation (no easing)
    class func LinearInterpolation(p : Double) -> Double {
    
        return p
    }
    
    // MARK: Quadratic easing; p^2
    class func QuadraticEaseIn(p : Double) -> Double {
        
        return p * p
    }
    
    class func QuadraticEaseOut(p : Double) -> Double {
        
        return -(p * (p - 2))
    }
    
    class func QuadraticEaseInOut(p : Double) -> Double {
        
        if (p < 0.5) {
            
            return 2 * p * p
            
        } else {
            
            return (-2 * p * p) + (4 * p) - 1
        }
    }
    
    // MARK: Cubic easing; p^3
    class func CubicEaseIn(p : Double) -> Double {
        
        return p * p * p
    }
    
    class func CubicEaseOut(p : Double) -> Double {
        
        let f : Double = (p - 1)
        return f * f * f + 1
    }
    
    class func CubicEaseInOut(p : Double) -> Double {
        
        if (p < 0.5) {
            
            return 4 * p * p * p
            
        } else {
            
            let f : Double = ((2 * p) - 2)
            return 0.5 * f * f * f + 1
        }
    }
    
    // MARK: Quartic easing; p^4
    class func QuarticEaseIn(p : Double) -> Double {
        
        return p * p * p * p
    }
    
    class func QuarticEaseOut(p : Double) -> Double {
        
        let f : Double = (p - 1)
        return f * f * f * (1 - p) + 1
    }
    
    class func QuarticEaseInOut(p : Double) -> Double {
        
        if(p < 0.5) {
            
            return 8 * p * p * p * p
            
        } else {
            
            let f : Double = (p - 1);
            return -8 * f * f * f * f + 1
        }
    }

    // MARK: Quintic easing; p^5
    class func QuinticEaseIn(p : Double) -> Double {
        
        return p * p * p * p * p
    }
    
    class func QuinticEaseOut(p : Double) -> Double {
        
        let f : Double = (p - 1)
        return f * f * f * f * f + 1
    }
    
    class func QuinticEaseInOut(p : Double) -> Double {
        
        if (p < 0.5) {
            
            return 16 * p * p * p * p * p
            
        } else {
            
            let f : Double = ((2 * p) - 2)
            return  0.5 * f * f * f * f * f + 1
        }
    }
    
    // MARK: Sine wave easing; sin(p * PI/2)
    class func SineEaseIn(p : Double) -> Double {
        
        return sin((p - 1) * M_PI_2) + 1
    }
    
    class func SineEaseOut(p : Double) -> Double {
        
        return sin(p * M_PI_2)
    }
    
    class func SineEaseInOut(p : Double) -> Double {
        
        return 0.5 * (1 - cos(p * M_PI))
    }

    // MARK: Circular easing; sqrt(1 - p^2)
    class func CircularEaseIn(p : Double) -> Double {
        
        return 1 - sqrt(1 - (p * p))
    }
    
    class func CircularEaseOut(p : Double) -> Double {
        
        return sqrt((2 - p) * p)
    }
    
    class func CircularEaseInOut(p : Double) -> Double {
        
        if (p < 0.5) {
            
            return 0.5 * (1 - sqrt(1 - 4 * (p * p)))
            
        } else {
            
            return 0.5 * (sqrt(-((2 * p) - 3) * ((2 * p) - 1)) + 1)
        }
    }

    // MARK: Exponential easing, base 2
    class func ExponentialEaseIn(p : Double) -> Double {
        
        return (p == 0.0) ? p : pow(2, 10 * (p - 1))
    }
    
    class func ExponentialEaseOut(p : Double) -> Double {
        
        return (p == 1.0) ? p : 1 - pow(2, -10 * p)
    }
    
    class func ExponentialEaseInOut(p : Double) -> Double {
        
        if (p == 0.0 || p == 1.0) {
            
            return p
        }
        
        if (p < 0.5) {
            
            return 0.5 * pow(2, (20 * p) - 10)
            
        } else {
            
            return -0.5 * pow(2, (-20 * p) + 10) + 1
        }
    }
    
    // MARK: Exponentially-damped sine wave easing
    class func ElasticEaseIn(p : Double) -> Double {
        
        return sin(13 * M_PI_2 * p) * pow(2, 10 * (p - 1))
    }
    
    class func ElasticEaseOut(p : Double) -> Double {
        
        return sin(-13 * M_PI_2 * (p + 1)) * pow(2, -10 * p) + 1
    }
    
    class func ElasticEaseInOut(p : Double) -> Double {
        
        if (p < 0.5) {
            
            return 0.5 * sin(13 * M_PI_2 * (2 * p)) * pow(2, 10 * ((2 * p) - 1))
            
        } else {
            
            return 0.5 * (sin(-13 * M_PI_2 * ((2 * p - 1) + 1)) * pow(2, -10 * (2 * p - 1)) + 2)
        }
    }

    // MARK: Overshooting cubic easing
    class func BackEaseIn(p : Double) -> Double {
        
        return p * p * p - p * sin(p * M_PI)
    }
    
    class func BackEaseOut(p : Double) -> Double {
        
        let f : Double = (1 - p);
        return 1 - (f * f * f - f * sin(f * M_PI))
    }
    
    class func BackEaseInOut(p : Double) -> Double {
        
        if (p < 0.5) {
            
            let f : Double = 2 * p
            return 0.5 * (f * f * f - f * sin(f * M_PI))
            
        } else {
            
            let f   : Double = (1 - (2*p - 1))
            let tmp : Double = (f * f * f - f * sin(f * M_PI))
            return 0.5 * (1 - tmp) + 0.5
        }
    }

    // MARK: Exponentially-decaying bounce easing
    class func BounceEaseIn(p : Double) -> Double {
        
        return 1 - BounceEaseOut(1 - p)
    }
    
    class func BounceEaseOut(p : Double) -> Double {
        
        if (p < 4/11.0) {
            
            return (121 * p * p)/16.0
            
        } else if (p < 8/11.0) {
            
            return (363/40.0 * p * p) - (99/10.0 * p) + 17/5.0
            
        } else if (p < 9/10.0) {
            
            return (4356/361.0 * p * p) - (35442/1805.0 * p) + 16061/1805.0
            
        } else {
            
            return (54/5.0 * p * p) - (513/25.0 * p) + 268/25.0
        }
    }
    
    class func BounceEaseInOut(p : Double) -> Double {
        
        if (p < 0.5) {
            
            return 0.5 * BounceEaseIn(p*2)
            
        } else {
            
            return 0.5 * BounceEaseOut(p * 2 - 1) + 0.5
        }
    }
}


//
//  EasingValue.swift
//  Swift-EasingAnimation
//
//  Created by YouXianMing on 15/10/21.
//
//  https://github.com/YouXianMing
//  http://home.cnblogs.com/u/YouXianMing/
//

import UIKit

class EasingValue: NSObject {
    
    // MARK: var
    
    /// 动画函数
    var function   : EasingFunction!
    
    /// 关键帧点数
    var frameCount : size_t!
    
    // MARK: init
    override init() {
        
        super.init()
        
        function   = EasingFunction.SineEaseIn
        frameCount = 60
    }
    
    init(withFunction : EasingFunction, frameCount : size_t) {
        
        super.init()
        
        self.function   = withFunction
        self.frameCount = frameCount
    }
    
    // MARK: func
    
    /**
    计算关键帧
    
    - parameter fromValue: 起始值
    - parameter toValue:   结束值
    
    - returns: 关键帧值数组
    */
    func frameValueWith(fromValue fromValue : Double, toValue : Double) -> [AnyObject] {
        
        let values = NSMutableArray(capacity: frameCount)
        
        var t  : Double = 0.0
        let dt : Double = 1.0 / (Double(frameCount) - 1)
        
        for var i = 0; i < frameCount; ++i, t += dt {
            
            let value = fromValue + (function.value())(t) * (toValue - fromValue)
            values.addObject(value)
        }
        
        return values as [AnyObject]
    }
    
    /**
    计算关键帧点
    
    - parameter fromPoint: 起始点
    - parameter toPoint:   结束点
    
    - returns: 关键帧点数组
    */
    func pointValueWith(fromPoint fromPoint : CGPoint, toPoint : CGPoint) -> [AnyObject] {
        
        let values = NSMutableArray(capacity: frameCount)
        
        var t  : Double = 0.0
        let dt : Double = 1.0 / (Double(frameCount) - 1)
        
        for var i = 0; i < frameCount; ++i, t += dt {
            
            let x     : Double  = Double(fromPoint.x) + (function.value())(t) * (Double(toPoint.x) - Double(fromPoint.x))
            let y     : Double  = Double(fromPoint.y) + (function.value())(t) * (Double(toPoint.y) - Double(fromPoint.y))
            let point : CGPoint = CGPoint(x : x, y : y)
            values.addObject(NSValue(CGPoint: point))
        }
        
        return values as [AnyObject]
    }
    
    /**
    计算关键帧尺寸
    
    - parameter fromSize: 起始尺寸
    - parameter toSize:   结束尺寸
    
    - returns: 关键帧尺寸数组
    */
    func sizeValueWith(fromSize fromSize : CGSize, toSize : CGSize) -> [AnyObject] {
        
        let values = NSMutableArray(capacity: frameCount)
        
        var t  : Double = 0.0
        let dt : Double = 1.0 / (Double(frameCount) - 1)
        
        for var i = 0; i < frameCount; ++i, t += dt {
            
            let width  : Double = Double(fromSize.width)  + (function.value())(t) * (Double(toSize.width) - Double(fromSize.width))
            let height : Double = Double(fromSize.height) + (function.value())(t) * (Double(toSize.height) - Double(fromSize.height))
            let size   : CGSize = CGSize(width: width, height: height)
            values.addObject(NSValue(CGSize : size))
        }
        
        return values as [AnyObject]
    }
}


//
//  ComplexEasingValue.swift
//  Swift-EasingAnimation
//
//  Created by YouXianMing on 15/10/21.
//
//  https://github.com/YouXianMing
//  http://home.cnblogs.com/u/YouXianMing/
//

import UIKit

class ComplexEasingValue: EasingValue {

    /// 点A的动画函数(如果是 size,则点 A 表示 width;如果是 point,则点 A 表示 x)
    var functionA  : EasingFunction!
    
    /// 点B的动画函数(如果是 size,则点 B 表示 height;如果是 point,则点 B 表示 y)
    var functionB  : EasingFunction!
    
    // MARK: init
    override init() {
        
        super.init()
        
        functionA  = EasingFunction.SineEaseIn
        functionB  = EasingFunction.SineEaseIn
        frameCount = 60
    }
    
    init(withFunctionA : EasingFunction, FunctionB : EasingFunction, frameCount : size_t) {
        
        super.init()
        
        functionA       = withFunctionA
        functionB       = FunctionB
        self.frameCount = frameCount
    }
    
    /**
    计算关键帧
    
    - parameter fromValue: 起始值
    - parameter toValue:   结束值
    
    - returns: 关键帧值数组
    */
    override func pointValueWith(fromPoint fromPoint : CGPoint, toPoint : CGPoint) -> [AnyObject] {
        
        let values = NSMutableArray(capacity: frameCount)
        
        var t  : Double = 0.0
        let dt : Double = 1.0 / (Double(frameCount) - 1)
        
        for var i = 0; i < frameCount; ++i, t += dt {
            
            let x     : Double  = Double(fromPoint.x) + (functionA.value())(t) * (Double(toPoint.x) - Double(fromPoint.x))
            let y     : Double  = Double(fromPoint.y) + (functionB.value())(t) * (Double(toPoint.y) - Double(fromPoint.y))
            let point : CGPoint = CGPoint(x : x, y : y)
            values.addObject(NSValue(CGPoint: point))
        }
        
        return values as [AnyObject]
    }
    
    /**
    计算关键帧点
    
    - parameter fromPoint: 起始点
    - parameter toPoint:   结束点
    
    - returns: 关键帧点数组
    */
    override func sizeValueWith(fromSize fromSize : CGSize, toSize : CGSize) -> [AnyObject] {
        
        let values = NSMutableArray(capacity: frameCount)
        
        var t  : Double = 0.0
        let dt : Double = 1.0 / (Double(frameCount) - 1)
        
        for var i = 0; i < frameCount; ++i, t += dt {
            
            let width  : Double = Double(fromSize.width)  + (functionA.value())(t) * (Double(toSize.width) - Double(fromSize.width))
            let height : Double = Double(fromSize.height) + (functionB.value())(t) * (Double(toSize.height) - Double(fromSize.height))
            let size   : CGSize = CGSize(width: width, height: height)
            values.addObject(NSValue(CGSize : size))
        }
        
        return values as [AnyObject]
    }
}

细节

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值