Skip to content
Snippets Groups Projects
Select Git revision
  • b4639b36a06c6a60fa384b4689925f97c2ba2af2
  • main default protected
  • development
  • integration
  • v1.1.5
  • v1.1.4
  • v1.1.3
  • v1.1.2
  • v1.1.1
  • v1.1.0
  • v1.0.0
11 results

JSONEncoder.swift

Blame
  • ManualAnimator.swift 2.55 KiB
    import UIKit
    import Foundation
    
    // https://github.com/ekazaev/ChatLayout
    
    final class ManualAnimator {
        enum AnimationCurve {
            case linear, parametric, easeInOut, easeIn, easeOut
    
            func modify(_ x: CGFloat) -> CGFloat {
                switch self {
                case .linear:
                    return x
                case .parametric:
                    return x.parametric
                case .easeInOut:
                    return x.quadraticEaseInOut
                case .easeIn:
                    return x.quadraticEaseIn
                case .easeOut:
                    return x.quadraticEaseOut
                }
            }
        }
    
        private var displayLink: CADisplayLink?
        private var start = Date()
        private var total = TimeInterval(0)
        private var closure: ((CGFloat) -> Void)?
        private var animationCurve: AnimationCurve = .linear
    
        func animate(duration: TimeInterval, curve: AnimationCurve = .linear, _ animations: @escaping (CGFloat) -> Void) {
            guard duration > 0 else {
                animations(1.0); return
            }
            reset()
            start = Date()
            closure = animations
            total = duration
            animationCurve = curve
            let d = CADisplayLink(target: self, selector: #selector(tick))
            d.add(to: .current, forMode: .common)
            displayLink = d
        }
    
        @objc private func tick() {
            let delta = Date().timeIntervalSince(start)
            var percentage = animationCurve.modify(CGFloat(delta) / CGFloat(total))
            if percentage < 0.0 {
                percentage = 0.0
            } else if percentage >= 1.0 {
                percentage = 1.0
                reset()
            }
    
            closure?(percentage)
        }
    
        private func reset() {
            displayLink?.invalidate()
            displayLink = nil
        }
    }
    
    extension CGFloat {
        fileprivate var parametric: CGFloat {
            guard self > 0.0 else { return 0.0 }
            guard self < 1.0 else { return 1.0 }
    
            return ((self * self) / (2.0 * ((self * self) - self) + 1.0))
        }
    
        fileprivate var quadraticEaseInOut: CGFloat {
            guard self > 0.0 else { return 0.0 }
            guard self < 1.0 else { return 1.0 }
    
            if self < 0.5 {
                return 2 * self * self
            }
    
            return (-2 * self * self) + (4 * self) - 1
        }
    
        fileprivate var quadraticEaseOut: CGFloat {
            guard self > 0.0 else { return 0.0 }
            guard self < 1.0 else { return 1.0 }
    
            return -self * (self - 2)
        }
    
        fileprivate var quadraticEaseIn: CGFloat {
            guard self > 0.0 else { return 0.0 }
            guard self < 1.0 else { return 1.0 }
    
            return self * self
        }
    }