Skip to content

Commit 2590d45

Browse files
Added portal animation from ZEN BabyBook app
Kindly contributed by FreddyF. Original source here: https://github.com/FredddyF/BabyBook-v2--iOS7-/blob/master/ZEN%20BabyBook/ZENPortalAnimationController.m
1 parent 9070b93 commit 2590d45

File tree

3 files changed

+175
-0
lines changed

3 files changed

+175
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// ZENPortalAnimationController.h
3+
// ZEN BabyBook
4+
//
5+
// Created by Frédéric ADDA on 07/12/2013.
6+
// Copyright (c) 2013 Frédéric ADDA. All rights reserved.
7+
//
8+
9+
#import "CEReversibleAnimationController.h"
10+
11+
/*
12+
Animates between the two view controllers using a portal-opening transition.
13+
*/
14+
15+
@interface ZENPortalAnimationController : CEReversibleAnimationController
16+
@end
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
//
2+
// ZENPortalAnimationController.m
3+
// ZEN BabyBook
4+
//
5+
// Created by Frédéric ADDA on 07/12/2013.
6+
// Copyright (c) 2013 Frédéric ADDA. All rights reserved.
7+
//
8+
9+
#import "ZENPortalAnimationController.h"
10+
11+
@implementation ZENPortalAnimationController
12+
13+
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {
14+
15+
if(self.reverse){
16+
[self executeReverseAnimation:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
17+
} else {
18+
[self executeForwardsAnimation:transitionContext fromVC:fromVC toVC:toVC fromView:fromView toView:toView];
19+
}
20+
21+
}
22+
23+
#define ZOOM_SCALE 0.8
24+
- (void)executeForwardsAnimation:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {
25+
26+
UIView *containerView = [transitionContext containerView];
27+
28+
// Add a reduced snapshot of the toView to the container
29+
UIView *toViewSnapshot = [toView resizableSnapshotViewFromRect:toView.frame afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero];
30+
CATransform3D scale = CATransform3DIdentity;
31+
toViewSnapshot.layer.transform = CATransform3DScale(scale, ZOOM_SCALE, ZOOM_SCALE, 1);
32+
[containerView addSubview:toViewSnapshot];
33+
[containerView sendSubviewToBack:toViewSnapshot];
34+
35+
36+
// Create two-part snapshots of the from- view
37+
38+
// snapshot the left-hand side of the from- view
39+
CGRect leftSnapshotRegion = CGRectMake(0, 0, fromView.frame.size.width / 2, fromView.frame.size.height);
40+
UIView *leftHandView = [fromView resizableSnapshotViewFromRect:leftSnapshotRegion afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
41+
leftHandView.frame = leftSnapshotRegion;
42+
[containerView addSubview:leftHandView];
43+
44+
// snapshot the right-hand side of the from- view
45+
CGRect rightSnapshotRegion = CGRectMake(fromView.frame.size.width / 2, 0, fromView.frame.size.width / 2, fromView.frame.size.height);
46+
UIView *rightHandView = [fromView resizableSnapshotViewFromRect:rightSnapshotRegion afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
47+
rightHandView.frame = rightSnapshotRegion;
48+
[containerView addSubview:rightHandView];
49+
50+
// remove the view that was snapshotted
51+
[fromView removeFromSuperview];
52+
53+
// animate
54+
NSTimeInterval duration = [self transitionDuration:transitionContext];
55+
56+
[UIView animateWithDuration:duration
57+
delay:0.0
58+
options:UIViewAnimationOptionCurveEaseOut
59+
animations:^{
60+
// Open the portal doors of the from-view
61+
leftHandView.frame = CGRectOffset(leftHandView.frame, - leftHandView.frame.size.width, 0);
62+
rightHandView.frame = CGRectOffset(rightHandView.frame, rightHandView.frame.size.width, 0);
63+
64+
// zoom in the to-view
65+
toViewSnapshot.center = toView.center;
66+
toViewSnapshot.frame = toView.frame;
67+
68+
} completion:^(BOOL finished) {
69+
70+
// remove all the temporary views
71+
if ([transitionContext transitionWasCancelled]) {
72+
[self removeOtherViews:fromView];
73+
} else {
74+
[self removeOtherViews:toView];
75+
}
76+
77+
// inform the context of completion
78+
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
79+
}];
80+
81+
}
82+
83+
84+
85+
- (void)executeReverseAnimation:(id<UIViewControllerContextTransitioning>)transitionContext fromVC:(UIViewController *)fromVC toVC:(UIViewController *)toVC fromView:(UIView *)fromView toView:(UIView *)toView {
86+
87+
UIView *containerView = [transitionContext containerView];
88+
89+
// Add the from-view to the container
90+
[containerView addSubview:fromView];
91+
92+
93+
// Create two-part snapshots of the to- view
94+
95+
// snapshot the left-hand side of the to- view
96+
CGRect leftSnapshotRegion = CGRectMake(0, 0, toView.frame.size.width / 2, toView.frame.size.height);
97+
UIView *leftHandView = [toView resizableSnapshotViewFromRect:leftSnapshotRegion afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero];
98+
leftHandView.frame = leftSnapshotRegion;
99+
// reverse animation : start from beyond the edges of the screen
100+
leftHandView.frame = CGRectOffset(leftHandView.frame, - leftHandView.frame.size.width, 0);
101+
[containerView addSubview:leftHandView];
102+
103+
// snapshot the right-hand side of the to- view
104+
CGRect rightSnapshotRegion = CGRectMake(toView.frame.size.width / 2, 0, toView.frame.size.width / 2, toView.frame.size.height);
105+
UIView *rightHandView = [toView resizableSnapshotViewFromRect:rightSnapshotRegion afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero];
106+
rightHandView.frame = rightSnapshotRegion;
107+
// reverse animation : start from beyond the edges of the screen
108+
rightHandView.frame = CGRectOffset(rightHandView.frame, rightHandView.frame.size.width, 0);
109+
[containerView addSubview:rightHandView];
110+
111+
// animate
112+
NSTimeInterval duration = [self transitionDuration:transitionContext];
113+
114+
115+
[UIView animateWithDuration:duration
116+
delay:0.0
117+
options:UIViewAnimationOptionCurveEaseOut
118+
animations:^{
119+
// Close the portal doors of the to-view
120+
leftHandView.frame = CGRectOffset(leftHandView.frame, leftHandView.frame.size.width, 0);
121+
rightHandView.frame = CGRectOffset(rightHandView.frame, - rightHandView.frame.size.width, 0);
122+
123+
// Zoom out the from-view
124+
CATransform3D scale = CATransform3DIdentity;
125+
fromView.layer.transform = CATransform3DScale(scale, ZOOM_SCALE, ZOOM_SCALE, 1);
126+
127+
128+
} completion:^(BOOL finished) {
129+
130+
// remove all the temporary views
131+
if ([transitionContext transitionWasCancelled]) {
132+
[self removeOtherViews:fromView];
133+
} else {
134+
[self removeOtherViews:toView];
135+
}
136+
137+
// inform the context of completion
138+
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
139+
}];
140+
}
141+
142+
143+
// removes all the views other than the given view from the superview
144+
- (void)removeOtherViews:(UIView*)viewToKeep {
145+
UIView *containerView = viewToKeep.superview;
146+
for (UIView *view in containerView.subviews) {
147+
if (view != viewToKeep) {
148+
[view removeFromSuperview];
149+
}
150+
}
151+
}
152+
153+
@end

TransitionsDemo/TransitionsDemo.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
7273236A17DFBF140072C7FD /* CEHorizontalSwipeInteractionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7273236817DFBF140072C7FD /* CEHorizontalSwipeInteractionController.m */; };
2727
7273236D17DFC0690072C7FD /* NavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7273236C17DFC0690072C7FD /* NavigationController.m */; };
2828
7273237017DFC4710072C7FD /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7273236F17DFC4710072C7FD /* SettingsViewController.m */; };
29+
72B92C661856FE98001A2D84 /* ZENPortalAnimationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 72B92C651856FE98001A2D84 /* ZENPortalAnimationController.m */; };
2930
72C15E1117E10C620056B3F9 /* CECrossfadeAnimationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 72C15E1017E10C620056B3F9 /* CECrossfadeAnimationController.m */; };
3031
72C15E1417E10E7B0056B3F9 /* CEExplodeAnimationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 72C15E1317E10E7B0056B3F9 /* CEExplodeAnimationController.m */; };
3132
72C15E1717E19A940056B3F9 /* CEFoldAnimationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 72C15E1617E19A940056B3F9 /* CEFoldAnimationController.m */; };
@@ -76,6 +77,8 @@
7677
7273236C17DFC0690072C7FD /* NavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NavigationController.m; sourceTree = "<group>"; };
7778
7273236E17DFC4710072C7FD /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = "<group>"; };
7879
7273236F17DFC4710072C7FD /* SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewController.m; sourceTree = "<group>"; };
80+
72B92C641856FE98001A2D84 /* ZENPortalAnimationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZENPortalAnimationController.h; sourceTree = "<group>"; };
81+
72B92C651856FE98001A2D84 /* ZENPortalAnimationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZENPortalAnimationController.m; sourceTree = "<group>"; };
7982
72C15E0F17E10C620056B3F9 /* CECrossfadeAnimationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CECrossfadeAnimationController.h; sourceTree = "<group>"; };
8083
72C15E1017E10C620056B3F9 /* CECrossfadeAnimationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CECrossfadeAnimationController.m; sourceTree = "<group>"; };
8184
72C15E1217E10E7B0056B3F9 /* CEExplodeAnimationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CEExplodeAnimationController.h; sourceTree = "<group>"; };
@@ -179,6 +182,8 @@
179182
7273235717DFBEBF0072C7FD /* AnimationControllers */ = {
180183
isa = PBXGroup;
181184
children = (
185+
72B92C641856FE98001A2D84 /* ZENPortalAnimationController.h */,
186+
72B92C651856FE98001A2D84 /* ZENPortalAnimationController.m */,
182187
7273236117DFBEFE0072C7FD /* CEReversibleAnimationController.h */,
183188
7273236217DFBEFE0072C7FD /* CEReversibleAnimationController.m */,
184189
7273235A17DFBEBF0072C7FD /* CEFlipAnimationController.h */,
@@ -314,6 +319,7 @@
314319
files = (
315320
7273236917DFBF140072C7FD /* CEBaseInteractionController.m in Sources */,
316321
7273233917DFBD4D0072C7FD /* ViewController.m in Sources */,
322+
72B92C661856FE98001A2D84 /* ZENPortalAnimationController.m in Sources */,
317323
72C15E1717E19A940056B3F9 /* CEFoldAnimationController.m in Sources */,
318324
72C15E1417E10E7B0056B3F9 /* CEExplodeAnimationController.m in Sources */,
319325
72C15E1117E10C620056B3F9 /* CECrossfadeAnimationController.m in Sources */,

0 commit comments

Comments
 (0)