Browse Source

Implement rotate animation for shared element transition

Yogev Ben David 4 years ago
parent
commit
5d9e9100b7
No account linked to committer's email address

+ 2
- 0
lib/ios/ElementBaseTransition.h View File

3
 #import "DisplayLinkAnimation.h"
3
 #import "DisplayLinkAnimation.h"
4
 #import "RNNInterpolator.h"
4
 #import "RNNInterpolator.h"
5
 
5
 
6
+#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
7
+
6
 @interface ElementBaseTransition : NSObject <DisplayLinkAnimation>
8
 @interface ElementBaseTransition : NSObject <DisplayLinkAnimation>
7
 
9
 
8
 - (instancetype)initWithView:(UIView *)view startDelay:(NSTimeInterval)startDelay duration:(NSTimeInterval)duration interpolation:(Text *)interpolation;
10
 - (instancetype)initWithView:(UIView *)view startDelay:(NSTimeInterval)startDelay duration:(NSTimeInterval)duration interpolation:(Text *)interpolation;

+ 2
- 0
lib/ios/FloatTransition.h View File

5
 
5
 
6
 - (instancetype)initWithView:(UIView *)view transitionDetails:(TransitionDetailsOptions *)transitionDetails;
6
 - (instancetype)initWithView:(UIView *)view transitionDetails:(TransitionDetailsOptions *)transitionDetails;
7
 
7
 
8
+- (instancetype)initWithView:(UIView *)view fromFloat:(CGFloat)from toFloat:(CGFloat)to startDelay:(NSTimeInterval)startDelay duration:(NSTimeInterval)duration interpolation:(Text *)interpolation;
9
+
8
 @property (readonly) CGFloat initialValue;
10
 @property (readonly) CGFloat initialValue;
9
 @property (nonatomic) CGFloat from;
11
 @property (nonatomic) CGFloat from;
10
 @property (nonatomic) CGFloat to;
12
 @property (nonatomic) CGFloat to;

+ 7
- 0
lib/ios/FloatTransition.m View File

12
     return self;
12
     return self;
13
 }
13
 }
14
 
14
 
15
+- (instancetype)initWithView:(UIView *)view fromFloat:(CGFloat)from toFloat:(CGFloat)to startDelay:(NSTimeInterval)startDelay duration:(NSTimeInterval)duration interpolation:(Text *)interpolation {
16
+    self = [super initWithView:view startDelay:startDelay duration:duration interpolation:interpolation];
17
+    self.from = from;
18
+    self.to = to;
19
+    return self;
20
+}
21
+
15
 - (instancetype)initWithView:(UIView *)view from:(Double*)from to:(Double*)to startDelay:(NSTimeInterval)startDelay duration:(NSTimeInterval)duration interpolation:(Text *)interpolation {
22
 - (instancetype)initWithView:(UIView *)view from:(Double*)from to:(Double*)to startDelay:(NSTimeInterval)startDelay duration:(NSTimeInterval)duration interpolation:(Text *)interpolation {
16
     self = [super initWithView:view startDelay:startDelay duration:duration interpolation:interpolation];
23
     self = [super initWithView:view startDelay:startDelay duration:duration interpolation:interpolation];
17
     _initialValue = self.initialValue;
24
     _initialValue = self.initialValue;

+ 2
- 0
lib/ios/RNNViewLocation.h View File

4
 
4
 
5
 @property (nonatomic) CGRect fromFrame;
5
 @property (nonatomic) CGRect fromFrame;
6
 @property (nonatomic) CGRect toFrame;
6
 @property (nonatomic) CGRect toFrame;
7
+@property (nonatomic) CGFloat fromAngle;
8
+@property (nonatomic) CGFloat toAngle;
7
 
9
 
8
 - (instancetype)initWithFromElement:(UIView*)fromElement toElement:(UIView*)toElement;
10
 - (instancetype)initWithFromElement:(UIView*)fromElement toElement:(UIView*)toElement;
9
 
11
 

+ 10
- 3
lib/ios/RNNViewLocation.m View File

8
 	self = [super init];
8
 	self = [super init];
9
     self.fromFrame = [self convertViewFrame:fromElement];
9
     self.fromFrame = [self convertViewFrame:fromElement];
10
     self.toFrame = [self convertViewFrame:toElement];
10
     self.toFrame = [self convertViewFrame:toElement];
11
+    self.fromAngle = [self getViewAngle:fromElement];
12
+    self.toAngle = [self getViewAngle:toElement];
11
 	return self;
13
 	return self;
12
 }
14
 }
13
 
15
 
14
 - (CGRect)convertViewFrame:(UIView *)view {
16
 - (CGRect)convertViewFrame:(UIView *)view {
15
     UIView* topMostView = [self topMostView:view];
17
     UIView* topMostView = [self topMostView:view];
16
-    CGRect frame = [view.superview convertRect:view.frame toView:nil];
18
+    CGPoint center = [view.superview convertPoint:view.center toView:nil];
17
     CGFloat safeAreaTopOffset = [self safeAreaOffsetForView:view inView:topMostView];
19
     CGFloat safeAreaTopOffset = [self safeAreaOffsetForView:view inView:topMostView];
18
-    frame.origin.y += safeAreaTopOffset;
19
-
20
+    center.y += safeAreaTopOffset;
21
+    CGRect frame = CGRectMake(center.x - view.bounds.size.width / 2, center.y - view.bounds.size.height / 2, view.bounds.size.width, view.bounds.size.height);
20
     return frame;
22
     return frame;
21
 }
23
 }
22
 
24
 
25
+- (CGFloat)getViewAngle:(UIView *)view {
26
+    CGFloat radians = atan2f(view.transform.b, view.transform.a);
27
+    return radians;
28
+}
29
+
23
  - (UIView *)topMostView:(UIView *)view {
30
  - (UIView *)topMostView:(UIView *)view {
24
     if ([view isKindOfClass:[RNNReactView class]]) {
31
     if ([view isKindOfClass:[RNNReactView class]]) {
25
         return view;
32
         return view;

+ 8
- 0
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

235
 		50644A2120E11A720026709C /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 50644A1F20E11A720026709C /* Constants.m */; };
235
 		50644A2120E11A720026709C /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 50644A1F20E11A720026709C /* Constants.m */; };
236
 		506A2B1420973DFD00F43A95 /* RNNErrorHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 506A2B1220973DFD00F43A95 /* RNNErrorHandler.h */; };
236
 		506A2B1420973DFD00F43A95 /* RNNErrorHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 506A2B1220973DFD00F43A95 /* RNNErrorHandler.h */; };
237
 		506A2B1520973DFD00F43A95 /* RNNErrorHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 506A2B1320973DFD00F43A95 /* RNNErrorHandler.m */; };
237
 		506A2B1520973DFD00F43A95 /* RNNErrorHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 506A2B1320973DFD00F43A95 /* RNNErrorHandler.m */; };
238
+		506C2532244F0C6B00820F5B /* RotationTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 506C2530244F0C6B00820F5B /* RotationTransition.h */; };
239
+		506C2533244F0C6B00820F5B /* RotationTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 506C2531244F0C6B00820F5B /* RotationTransition.m */; };
238
 		506F630D216A599300AD0D0A /* RNNTabBarControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 506F630C216A599300AD0D0A /* RNNTabBarControllerTest.m */; };
240
 		506F630D216A599300AD0D0A /* RNNTabBarControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 506F630C216A599300AD0D0A /* RNNTabBarControllerTest.m */; };
239
 		506F630F216A5AD700AD0D0A /* RNNComponentPresenterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 506F630E216A5AD700AD0D0A /* RNNComponentPresenterTest.m */; };
241
 		506F630F216A5AD700AD0D0A /* RNNComponentPresenterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 506F630E216A5AD700AD0D0A /* RNNComponentPresenterTest.m */; };
240
 		50706E6D20CE7CA5003345C3 /* UIImage+tint.h in Headers */ = {isa = PBXBuildFile; fileRef = 50706E6B20CE7CA5003345C3 /* UIImage+tint.h */; };
242
 		50706E6D20CE7CA5003345C3 /* UIImage+tint.h in Headers */ = {isa = PBXBuildFile; fileRef = 50706E6B20CE7CA5003345C3 /* UIImage+tint.h */; };
721
 		50644A1F20E11A720026709C /* Constants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = "<group>"; };
723
 		50644A1F20E11A720026709C /* Constants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = "<group>"; };
722
 		506A2B1220973DFD00F43A95 /* RNNErrorHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNErrorHandler.h; sourceTree = "<group>"; };
724
 		506A2B1220973DFD00F43A95 /* RNNErrorHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNErrorHandler.h; sourceTree = "<group>"; };
723
 		506A2B1320973DFD00F43A95 /* RNNErrorHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNErrorHandler.m; sourceTree = "<group>"; };
725
 		506A2B1320973DFD00F43A95 /* RNNErrorHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNErrorHandler.m; sourceTree = "<group>"; };
726
+		506C2530244F0C6B00820F5B /* RotationTransition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RotationTransition.h; sourceTree = "<group>"; };
727
+		506C2531244F0C6B00820F5B /* RotationTransition.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RotationTransition.m; sourceTree = "<group>"; };
724
 		506F630C216A599300AD0D0A /* RNNTabBarControllerTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTabBarControllerTest.m; sourceTree = "<group>"; };
728
 		506F630C216A599300AD0D0A /* RNNTabBarControllerTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTabBarControllerTest.m; sourceTree = "<group>"; };
725
 		506F630E216A5AD700AD0D0A /* RNNComponentPresenterTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNComponentPresenterTest.m; sourceTree = "<group>"; };
729
 		506F630E216A5AD700AD0D0A /* RNNComponentPresenterTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNComponentPresenterTest.m; sourceTree = "<group>"; };
726
 		50706E6B20CE7CA5003345C3 /* UIImage+tint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+tint.h"; sourceTree = "<group>"; };
730
 		50706E6B20CE7CA5003345C3 /* UIImage+tint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImage+tint.h"; sourceTree = "<group>"; };
1320
 				50AD288723CDB71C00FF3134 /* ElementHorizontalTransition.m */,
1324
 				50AD288723CDB71C00FF3134 /* ElementHorizontalTransition.m */,
1321
 				5082CC3123CDC3B800FD2B6A /* HorizontalTranslationTransition.h */,
1325
 				5082CC3123CDC3B800FD2B6A /* HorizontalTranslationTransition.h */,
1322
 				5082CC3223CDC3B800FD2B6A /* HorizontalTranslationTransition.m */,
1326
 				5082CC3223CDC3B800FD2B6A /* HorizontalTranslationTransition.m */,
1327
+				506C2530244F0C6B00820F5B /* RotationTransition.h */,
1328
+				506C2531244F0C6B00820F5B /* RotationTransition.m */,
1323
 				5061B6C523D48449008B9827 /* VerticalRotationTransition.h */,
1329
 				5061B6C523D48449008B9827 /* VerticalRotationTransition.h */,
1324
 				5061B6C623D48449008B9827 /* VerticalRotationTransition.m */,
1330
 				5061B6C623D48449008B9827 /* VerticalRotationTransition.m */,
1325
 				5096709923D49B35002224F9 /* DisplayLinkAnimatorDelegate.h */,
1331
 				5096709923D49B35002224F9 /* DisplayLinkAnimatorDelegate.h */,
1812
 				390AD477200F499D00A8250D /* RNNSwizzles.h in Headers */,
1818
 				390AD477200F499D00A8250D /* RNNSwizzles.h in Headers */,
1813
 				5022EDC924054C8A00852BA6 /* BottomTabsPresenterCreator.h in Headers */,
1819
 				5022EDC924054C8A00852BA6 /* BottomTabsPresenterCreator.h in Headers */,
1814
 				263905B11E4C6F440023D7D3 /* MMDrawerController.h in Headers */,
1820
 				263905B11E4C6F440023D7D3 /* MMDrawerController.h in Headers */,
1821
+				506C2532244F0C6B00820F5B /* RotationTransition.h in Headers */,
1815
 				263905B31E4C6F440023D7D3 /* MMDrawerVisualState.h in Headers */,
1822
 				263905B31E4C6F440023D7D3 /* MMDrawerVisualState.h in Headers */,
1816
 				50451D092042E20600695F00 /* RNNAnimationsOptions.h in Headers */,
1823
 				50451D092042E20600695F00 /* RNNAnimationsOptions.h in Headers */,
1817
 				50EA541A23AEE1C6006F881A /* AnimatedReactView.h in Headers */,
1824
 				50EA541A23AEE1C6006F881A /* AnimatedReactView.h in Headers */,
2182
 				50EA541B23AEE1C6006F881A /* AnimatedReactView.m in Sources */,
2189
 				50EA541B23AEE1C6006F881A /* AnimatedReactView.m in Sources */,
2183
 				5095BB732416A3B900C4CD41 /* RNNConvert.m in Sources */,
2190
 				5095BB732416A3B900C4CD41 /* RNNConvert.m in Sources */,
2184
 				7BC9346E1E26886E00EFA125 /* RNNControllerFactory.m in Sources */,
2191
 				7BC9346E1E26886E00EFA125 /* RNNControllerFactory.m in Sources */,
2192
+				506C2533244F0C6B00820F5B /* RotationTransition.m in Sources */,
2185
 				507F43F91FF525B500D9425B /* RNNSegmentedControl.m in Sources */,
2193
 				507F43F91FF525B500D9425B /* RNNSegmentedControl.m in Sources */,
2186
 				5038A3B2216DF41B009280BC /* UIViewController+RNNOptions.m in Sources */,
2194
 				5038A3B2216DF41B009280BC /* UIViewController+RNNOptions.m in Sources */,
2187
 				50D031352005149000386B3D /* RNNOverlayManager.m in Sources */,
2195
 				50D031352005149000386B3D /* RNNOverlayManager.m in Sources */,

+ 5
- 0
lib/ios/RotationTransition.h View File

1
+#import "FloatTransition.h"
2
+
3
+@interface RotationTransition : FloatTransition
4
+
5
+@end

+ 11
- 0
lib/ios/RotationTransition.m View File

1
+#import "RotationTransition.h"
2
+
3
+@implementation RotationTransition
4
+
5
+- (CATransform3D)animateWithProgress:(CGFloat)p {
6
+    double degrees = [RNNInterpolator fromFloat:self.from toFloat:self.to precent:p interpolation:self.interpolation];
7
+    double rads = DEGREES_TO_RADIANS(degrees);
8
+    return CATransform3DMakeRotation(rads, 0, 0, 1);
9
+}
10
+
11
+@end

+ 2
- 1
lib/ios/SharedElementAnimator.m View File

2
 #import "AnimatedViewFactory.h"
2
 #import "AnimatedViewFactory.h"
3
 #import "RectTransition.h"
3
 #import "RectTransition.h"
4
 #import "TransformRectTransition.h"
4
 #import "TransformRectTransition.h"
5
+#import "RotationTransition.h"
5
 #import "ColorTransition.h"
6
 #import "ColorTransition.h"
6
 #import "AnimatedTextView.h"
7
 #import "AnimatedTextView.h"
7
 #import "TextStorageTransition.h"
8
 #import "TextStorageTransition.h"
43
         if ([self.view isKindOfClass:AnimatedTextView.class]) {
44
         if ([self.view isKindOfClass:AnimatedTextView.class]) {
44
             [animations addObject:[[RectTransition alloc] initWithView:self.view from:self.view.location.fromFrame to:self.view.location.toFrame startDelay:startDelay duration:duration interpolation:interpolation]];
45
             [animations addObject:[[RectTransition alloc] initWithView:self.view from:self.view.location.fromFrame to:self.view.location.toFrame startDelay:startDelay duration:duration interpolation:interpolation]];
45
         } else {
46
         } else {
46
-            [animations addObject:[[TransformRectTransition alloc] initWithView:self.view from:self.view.location.fromFrame to:self.view.location.toFrame startDelay:startDelay duration:duration interpolation:interpolation]];
47
+            [animations addObject:[[TransformRectTransition alloc] initWithView:self.view fromRect:self.view.location.fromFrame toRect:self.view.location.toFrame fromAngle:self.view.location.fromAngle toAngle:self.view.location.toAngle startDelay:startDelay duration:duration interpolation:interpolation]];
47
         }
48
         }
48
     }
49
     }
49
     
50
     

+ 5
- 0
lib/ios/TransformRectTransition.h View File

3
 
3
 
4
 @interface TransformRectTransition : RectTransition
4
 @interface TransformRectTransition : RectTransition
5
 
5
 
6
+- (instancetype)initWithView:(UIView *)view fromRect:(CGRect)fromRect toRect:(CGRect)toRect fromAngle:(CGFloat)fromAngle toAngle:(CGFloat)toAngle startDelay:(NSTimeInterval)startDelay duration:(NSTimeInterval)duration interpolation:(Text *)interpolation;
7
+
8
+@property (nonatomic, readonly) CGFloat fromAngle;
9
+@property (nonatomic, readonly) CGFloat toAngle;
10
+
6
 @end
11
 @end

+ 10
- 1
lib/ios/TransformRectTransition.m View File

2
 
2
 
3
 @implementation TransformRectTransition
3
 @implementation TransformRectTransition
4
 
4
 
5
+- (instancetype)initWithView:(UIView *)view fromRect:(CGRect)fromRect toRect:(CGRect)toRect fromAngle:(CGFloat)fromAngle toAngle:(CGFloat)toAngle startDelay:(NSTimeInterval)startDelay duration:(NSTimeInterval)duration interpolation:(Text *)interpolation {
6
+    self = [super initWithView:view from:fromRect to:toRect startDelay:startDelay duration:duration interpolation:interpolation];
7
+    _fromAngle = fromAngle;
8
+    _toAngle = toAngle;
9
+    return self;
10
+}
11
+
5
 - (CATransform3D)animateWithProgress:(CGFloat)p {
12
 - (CATransform3D)animateWithProgress:(CGFloat)p {
6
     CGRect toFrame = [RNNInterpolator fromRect:self.from toRect:self.to precent:p interpolation:self.interpolation];
13
     CGRect toFrame = [RNNInterpolator fromRect:self.from toRect:self.to precent:p interpolation:self.interpolation];
14
+    CGFloat toAngle = [RNNInterpolator fromFloat:self.fromAngle toFloat:self.toAngle precent:p interpolation:self.interpolation];
7
     
15
     
8
     CGFloat scaleX = toFrame.size.width / self.from.size.width;
16
     CGFloat scaleX = toFrame.size.width / self.from.size.width;
9
     CGFloat scaleY = toFrame.size.height / self.from.size.height;
17
     CGFloat scaleY = toFrame.size.height / self.from.size.height;
14
     
22
     
15
     CATransform3D translate = CATransform3DMakeTranslation(translateX, translateY, 0);
23
     CATransform3D translate = CATransform3DMakeTranslation(translateX, translateY, 0);
16
     CATransform3D scale = CATransform3DScale(translate, scaleX, scaleY, 0);
24
     CATransform3D scale = CATransform3DScale(translate, scaleX, scaleY, 0);
25
+    CATransform3D rotate = CATransform3DRotate(scale, toAngle, 0, 0, 1);
17
     
26
     
18
-    return scale;
27
+    return rotate;
19
 }
28
 }
20
 
29
 
21
 @end
30
 @end

+ 0
- 1
lib/ios/VerticalRotationTransition.m View File

1
 #import "VerticalRotationTransition.h"
1
 #import "VerticalRotationTransition.h"
2
-#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
3
 
2
 
4
 @implementation VerticalRotationTransition
3
 @implementation VerticalRotationTransition
5
 
4