18
18
19
19
#import < UIKit/UIKit.h>
20
20
21
- #if TARGET_IPHONE_SIMULATOR
22
- UIKIT_EXTERN float UIAnimationDragCoefficient (void ); // UIKit private drag coefficient.
23
- #endif
24
-
25
- static CGFloat simulatorAnimationDragCoefficient (void ) {
26
- #if TARGET_IPHONE_SIMULATOR
27
- return UIAnimationDragCoefficient ();
28
- #else
29
- return 1.0 ;
30
- #endif
31
- }
32
-
33
- static CAMediaTimingFunction * timingFunctionWithControlPoints (CGFloat controlPoints[4 ]);
34
- static NSArray * coerceUIKitValuesToCoreAnimationValues (NSArray *values);
35
- static CABasicAnimation *animationFromTiming (MDMMotionTiming timing, CGFloat timeScaleFactor);
36
- static void makeAnimationAdditive (CABasicAnimation *animation);
21
+ #import " private/CABasicAnimation+MotionAnimator.h"
22
+ #import " private/MDMUIKitValueCoercion.h"
23
+ #import " private/MDMDragCoefficient.h"
37
24
38
25
@implementation MDMMotionAnimator {
39
26
NSMutableArray *_tracers;
@@ -65,7 +52,7 @@ - (void)animateWithTiming:(MDMMotionTiming)timing
65
52
if (_shouldReverseValues) {
66
53
values = [[values reverseObjectEnumerator ] allObjects ];
67
54
}
68
- values = coerceUIKitValuesToCoreAnimationValues (values);
55
+ values = MDMCoerceUIKitValuesToCoreAnimationValues (values);
69
56
70
57
if (timing.duration == 0 || timing.curve .type == MDMMotionCurveTypeInstant) {
71
58
[layer setValue: [values lastObject ] forKeyPath: keyPath];
@@ -75,8 +62,8 @@ - (void)animateWithTiming:(MDMMotionTiming)timing
75
62
return ;
76
63
}
77
64
78
- CGFloat timeScaleFactor = simulatorAnimationDragCoefficient () * _timeScaleFactor;
79
- CABasicAnimation *animation = animationFromTiming (timing, timeScaleFactor);
65
+ CGFloat timeScaleFactor = MDMSimulatorAnimationDragCoefficient () * _timeScaleFactor;
66
+ CABasicAnimation *animation = MDMAnimationFromTiming (timing, timeScaleFactor);
80
67
81
68
if (animation) {
82
69
animation.keyPath = keyPath;
@@ -97,7 +84,7 @@ - (void)animateWithTiming:(MDMMotionTiming)timing
97
84
98
85
if (![animation.fromValue isEqual: animation.toValue]) {
99
86
if (self.additive ) {
100
- makeAnimationAdditive (animation);
87
+ MDMMakeAnimationAdditive (animation);
101
88
}
102
89
103
90
if (timing.delay != 0 ) {
@@ -137,103 +124,3 @@ - (void)addCoreAnimationTracer:(void (^)(CALayer *, CAAnimation *))tracer {
137
124
138
125
@end
139
126
140
- static CAMediaTimingFunction * timingFunctionWithControlPoints (CGFloat controlPoints[4 ]) {
141
- return [CAMediaTimingFunction functionWithControlPoints: (float )controlPoints[0 ]
142
- :(float )controlPoints[1 ]
143
- :(float )controlPoints[2 ]
144
- :(float )controlPoints[3 ]];
145
- }
146
-
147
- static NSArray * coerceUIKitValuesToCoreAnimationValues (NSArray *values) {
148
- if ([[values firstObject ] isKindOfClass: [UIColor class ]]) {
149
- NSMutableArray *convertedArray = [NSMutableArray arrayWithCapacity: values.count];
150
- for (UIColor *color in values) {
151
- [convertedArray addObject: (id )color.CGColor ];
152
- }
153
- values = convertedArray;
154
-
155
- } else if ([[values firstObject ] isKindOfClass: [UIBezierPath class ]]) {
156
- NSMutableArray *convertedArray = [NSMutableArray arrayWithCapacity: values.count];
157
- for (UIBezierPath *bezierPath in values) {
158
- [convertedArray addObject: (id )bezierPath.CGPath ];
159
- }
160
- values = convertedArray;
161
- }
162
- return values;
163
- }
164
-
165
- static CABasicAnimation *animationFromTiming (MDMMotionTiming timing, CGFloat timeScaleFactor) {
166
- CABasicAnimation *animation;
167
- switch (timing.curve .type ) {
168
- case MDMMotionCurveTypeInstant:
169
- animation = nil ;
170
- break ;
171
-
172
- case MDMMotionCurveTypeDefault:
173
- case MDMMotionCurveTypeBezier:
174
- animation = [CABasicAnimation animation ];
175
- animation.timingFunction = timingFunctionWithControlPoints (timing.curve .data );
176
- animation.duration = timing.duration * timeScaleFactor;
177
- break ;
178
-
179
- case MDMMotionCurveTypeSpring: {
180
- #pragma clang diagnostic push
181
- // CASpringAnimation is a private API on iOS 8 - we're able to make use of it because we're
182
- // linking against the public API on iOS 9+.
183
- #pragma clang diagnostic ignored "-Wpartial-availability"
184
- CASpringAnimation *spring = [CASpringAnimation animation ];
185
- #pragma clang diagnostic pop
186
- spring.mass = timing.curve .data [MDMSpringMotionCurveDataIndexMass];
187
- spring.stiffness = timing.curve .data [MDMSpringMotionCurveDataIndexTension];
188
- spring.damping = timing.curve .data [MDMSpringMotionCurveDataIndexFriction];
189
-
190
- // This API is only available on iOS 9+
191
- if ([spring respondsToSelector: @selector (settlingDuration )]) {
192
- spring.duration = spring.settlingDuration ;
193
- } else {
194
- spring.duration = timing.duration ;
195
- }
196
- animation = spring;
197
- break ;
198
- }
199
- }
200
- return animation;
201
- }
202
-
203
- static void makeAnimationAdditive (CABasicAnimation *animation) {
204
- static NSSet *sizeKeyPaths = nil ;
205
- static NSSet *positionKeyPaths = nil ;
206
- static dispatch_once_t onceToken;
207
- dispatch_once (&onceToken, ^{
208
- sizeKeyPaths = [NSSet setWithArray: @[@" bounds.size" ]];
209
-
210
- positionKeyPaths = [NSSet setWithArray: @[@" position" ,
211
- @" anchorPoint" ]];
212
- });
213
-
214
- if ([animation.toValue isKindOfClass: [NSNumber class ]]) {
215
- CGFloat currentValue = (CGFloat )[animation.fromValue doubleValue ];
216
- CGFloat delta = currentValue - (CGFloat )[animation.toValue doubleValue ];
217
- animation.fromValue = @(delta);
218
- animation.toValue = @0 ;
219
- animation.additive = true ;
220
-
221
- } else if ([sizeKeyPaths containsObject: animation.keyPath]) {
222
- CGSize currentValue = [animation.fromValue CGSizeValue ];
223
- CGSize destinationValue = [animation.toValue CGSizeValue ];
224
- CGSize delta = CGSizeMake (currentValue.width - destinationValue.width ,
225
- currentValue.height - destinationValue.height );
226
- animation.fromValue = [NSValue valueWithCGSize: delta];
227
- animation.toValue = [NSValue valueWithCGSize: CGSizeZero ];
228
- animation.additive = true ;
229
-
230
- } else if ([positionKeyPaths containsObject: animation.keyPath]) {
231
- CGPoint currentValue = [animation.fromValue CGPointValue ];
232
- CGPoint destinationValue = [animation.toValue CGPointValue ];
233
- CGPoint delta = CGPointMake (currentValue.x - destinationValue.x ,
234
- currentValue.y - destinationValue.y );
235
- animation.fromValue = [NSValue valueWithCGPoint: delta];
236
- animation.toValue = [NSValue valueWithCGPoint: CGPointZero ];
237
- animation.additive = true ;
238
- }
239
- }
0 commit comments