1*e870aeeeSŁukasz Kosmaty //  Copyright (c) 2018, Applidium. All rights reserved
2*e870aeeeSŁukasz Kosmaty //  SpringOverlayTranslationAnimationController.swift
3*e870aeeeSŁukasz Kosmaty //  OverlayContainer
4*e870aeeeSŁukasz Kosmaty //
5*e870aeeeSŁukasz Kosmaty //  Created by Gaétan Zanella on 21/11/2018.
6*e870aeeeSŁukasz Kosmaty //
7*e870aeeeSŁukasz Kosmaty 
8*e870aeeeSŁukasz Kosmaty import UIKit
9*e870aeeeSŁukasz Kosmaty 
10*e870aeeeSŁukasz Kosmaty private struct Constant {
11*e870aeeeSŁukasz Kosmaty     static let defaultMass: CGFloat = 1
12*e870aeeeSŁukasz Kosmaty     static let defaultDamping: CGFloat = 0.7
13*e870aeeeSŁukasz Kosmaty     static let defaultRigidDamping: CGFloat = 0.9
14*e870aeeeSŁukasz Kosmaty     static let defaultResponse: CGFloat = 0.3
15*e870aeeeSŁukasz Kosmaty     static let minimumDamping: CGFloat = 1
16*e870aeeeSŁukasz Kosmaty     static let minimumVelocityConsideration: CGFloat = 150
17*e870aeeeSŁukasz Kosmaty     static let maximumVelocityConsideration: CGFloat = 3000
18*e870aeeeSŁukasz Kosmaty }
19*e870aeeeSŁukasz Kosmaty 
20*e870aeeeSŁukasz Kosmaty /// An `OverlayAnimatedTransitioning` implementation based on `UISpringTimingParameters`.
21*e870aeeeSŁukasz Kosmaty public class SpringOverlayTranslationAnimationController: OverlayAnimatedTransitioning {
22*e870aeeeSŁukasz Kosmaty 
23*e870aeeeSŁukasz Kosmaty     public var mass: CGFloat = Constant.defaultMass
24*e870aeeeSŁukasz Kosmaty     public var damping: CGFloat = Constant.defaultDamping
25*e870aeeeSŁukasz Kosmaty     public var response: CGFloat = Constant.defaultResponse
26*e870aeeeSŁukasz Kosmaty 
27*e870aeeeSŁukasz Kosmaty     // MARK: - Life Cycle
28*e870aeeeSŁukasz Kosmaty 
29*e870aeeeSŁukasz Kosmaty     public init() {}
30*e870aeeeSŁukasz Kosmaty 
31*e870aeeeSŁukasz Kosmaty     public init(style: OverlayContainerViewController.OverlayStyle) {
32*e870aeeeSŁukasz Kosmaty         switch style {
33*e870aeeeSŁukasz Kosmaty         case .expandableHeight, .rigid:
34*e870aeeeSŁukasz Kosmaty             // (gz) 2019-06-15 We also nullify the damping value when using rigid styles
35*e870aeeeSŁukasz Kosmaty             // to avoid the panel to be lifted above the bottom of the screen.
36*e870aeeeSŁukasz Kosmaty             damping = Constant.defaultRigidDamping
37*e870aeeeSŁukasz Kosmaty         case .flexibleHeight:
38*e870aeeeSŁukasz Kosmaty             damping = Constant.defaultDamping
39*e870aeeeSŁukasz Kosmaty         }
40*e870aeeeSŁukasz Kosmaty     }
41*e870aeeeSŁukasz Kosmaty 
42*e870aeeeSŁukasz Kosmaty     // MARK: - OverlayAnimatedTransitioning
43*e870aeeeSŁukasz Kosmaty 
interruptibleAnimatornull44*e870aeeeSŁukasz Kosmaty     public func interruptibleAnimator(using context: OverlayContainerContextTransitioning) -> UIViewImplicitlyAnimating {
45*e870aeeeSŁukasz Kosmaty         let velocity = min(
46*e870aeeeSŁukasz Kosmaty             Constant.maximumVelocityConsideration,
47*e870aeeeSŁukasz Kosmaty             max(abs(context.velocity.y), Constant.minimumVelocityConsideration)
48*e870aeeeSŁukasz Kosmaty         )
49*e870aeeeSŁukasz Kosmaty         let velocityRange = Constant.maximumVelocityConsideration - Constant.minimumVelocityConsideration
50*e870aeeeSŁukasz Kosmaty         let normalizedVelocity = (velocity - Constant.minimumVelocityConsideration) / velocityRange
51*e870aeeeSŁukasz Kosmaty         let normalizedDamping = normalizedVelocity * (damping - Constant.minimumDamping) + Constant.minimumDamping
52*e870aeeeSŁukasz Kosmaty         let timing = UISpringTimingParameters(
53*e870aeeeSŁukasz Kosmaty             damping: normalizedDamping,
54*e870aeeeSŁukasz Kosmaty             response: response,
55*e870aeeeSŁukasz Kosmaty             mass: mass
56*e870aeeeSŁukasz Kosmaty         )
57*e870aeeeSŁukasz Kosmaty         return UIViewPropertyAnimator(
58*e870aeeeSŁukasz Kosmaty             duration: 0, // duration is ignored when using `UISpringTimingParameters.init(mass:stiffness:damping:initialVelocity)`
59*e870aeeeSŁukasz Kosmaty             timingParameters: timing
60*e870aeeeSŁukasz Kosmaty         )
61*e870aeeeSŁukasz Kosmaty     }
62*e870aeeeSŁukasz Kosmaty }
63*e870aeeeSŁukasz Kosmaty 
64*e870aeeeSŁukasz Kosmaty extension UISpringTimingParameters {
65*e870aeeeSŁukasz Kosmaty     convenience init(damping: CGFloat, response: CGFloat, mass: CGFloat) {
66*e870aeeeSŁukasz Kosmaty         let stiffness = pow(2 * .pi / response, 2)
67*e870aeeeSŁukasz Kosmaty         let damp = 4 * .pi * damping / response
68*e870aeeeSŁukasz Kosmaty         self.init(mass: mass, stiffness: stiffness, damping: damp, initialVelocity: .zero)
69*e870aeeeSŁukasz Kosmaty     }
70*e870aeeeSŁukasz Kosmaty }
71