宽窄优行-由【嘉易行】项目成品而来
younger_times
2023-04-06 a1ae6802080a22e6e6ce6d0935e95facb1daca5c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
//
//  EKAttributes+Animation.swift
//  SwiftEntryKit
//
//  Created by Daniel Huri on 4/21/18.
//  Copyright (c) 2018 huri000@gmail.com. All rights reserved.
//
 
import UIKit
 
// A protocol that describes an animation
protocol EKAnimation {
    var delay: TimeInterval { get set }
    var duration: TimeInterval { get set }
    var spring: EKAttributes.Animation.Spring? { get set }
}
 
// A protocol that describes a range animation
protocol EKRangeAnimation: EKAnimation {
    var start: CGFloat { get set }
    var end: CGFloat { get set }
}
 
public extension EKAttributes {
    
    /** Describes an animation that can be performed on the entry */
    struct Animation: Equatable {
    
        /** Describes properties for a spring animation that can be performed on the entry */
        public struct Spring: Equatable {
            
            /** The dampic of the spring animation */
            public var damping: CGFloat
            
            /** The initial velocity of the spring animation */
            public var initialVelocity: CGFloat
            
            /** Initializer */
            public init(damping: CGFloat, initialVelocity: CGFloat) {
                self.damping = damping
                self.initialVelocity = initialVelocity
            }
        }
 
        /** Describes an animation with range */
        public struct RangeAnimation: EKRangeAnimation, Equatable {
            
            /** The duration of the range animation */
            public var duration: TimeInterval
            
            /** The delay of the range animation */
            public var delay: TimeInterval
            
            /** The start value of the range animation (e.g. alpha, scale) */
            public var start: CGFloat
            
            /** The end value of the range animation (e.g. alpha, scale) */
            public var end: CGFloat
            
            /** The spring of the animation */
            public var spring: Spring?
            
            /** Initializer */
            public init(from start: CGFloat, to end: CGFloat, duration: TimeInterval, delay: TimeInterval = 0, spring: Spring? = nil) {
                self.start = start
                self.end = end
                self.delay = delay
                self.duration = duration
                self.spring = spring
            }
        }
        
        /** Describes translation animation */
        public struct Translate: EKAnimation, Equatable {
            
            /** Describes the anchor position */
            public enum AnchorPosition: Equatable {
                
                /** Top position - the entry shows from top or exits towards the top */
                case top
                
                /** Bottom position - the entry shows from bottom or exits towards the bottom */
                case bottom
                
                /** Automatic position - the entry shows and exits according to EKAttributes.Position value. If the position of the entry is top, bottom, the entry's translation anchor is top, bottom - respectively.*/
                case automatic
            }
            
            /** Animation duration */
            public var duration: TimeInterval
            
            /** Animation delay */
            public var delay: TimeInterval
            
            /** To where OR from the entry is animated */
            public var anchorPosition: AnchorPosition
            
            /** Optional translation spring */
            public var spring: Spring?
 
            /** Initializer */
            public init(duration: TimeInterval, anchorPosition: AnchorPosition = .automatic, delay: TimeInterval = 0, spring: Spring? = nil) {
                self.anchorPosition = anchorPosition
                self.duration = duration
                self.delay = delay
                self.spring = spring
            }
        }
        
        /** Translation animation prop */
        public var translate: Translate?
        
        /** Scale animation prop */
        public var scale: RangeAnimation?
        
        /** Fade animation prop */
        public var fade: RangeAnimation?
        
        /** Does the animation contains translation */
        public var containsTranslation: Bool {
            return translate != nil
        }
        
        /** Does the animation contains scale */
        public var containsScale: Bool {
            return scale != nil
        }
        
        /** Does the animation contains fade */
        public var containsFade: Bool {
            return fade != nil
        }
        
        /** Does the animation contains any animation whatsoever */
        public var containsAnimation: Bool {
            return containsTranslation || containsScale || containsFade
        }
        
        /** Returns the maximum delay amongst all animations */
        public var maxDelay: TimeInterval {
            return max(translate?.delay ?? 0, max(scale?.delay ?? 0, fade?.delay ?? 0))
        }
        
        /** Returns the maximum duration amongst all animations */
        public var maxDuration: TimeInterval {
            return max(translate?.duration ?? 0, max(scale?.duration ?? 0, fade?.duration ?? 0))
        }
        
        /** Returns the maximum (duration+delay) amongst all animations */
        public var totalDuration: TimeInterval {
            return maxDelay + maxDuration
        }
        
        /** Returns the maximum (duration+delay) amongst all animations */
        public static var translation: Animation {
            return Animation(translate: .init(duration: 0.3))
        }
        
        /** No animation at all */
        public static var none: Animation {
            return Animation()
        }
        
        /** Initializer */
        public init(translate: Translate? = nil, scale: RangeAnimation? = nil, fade: RangeAnimation? = nil) {
            self.translate = translate
            self.scale = scale
            self.fade = fade
        }
    }
}