-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
086bb78
commit fd5c6f6
Showing
5 changed files
with
199 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// Animation.h | ||
// Pods | ||
// | ||
// Created by Wadah Esam on 04/11/2023. | ||
// | ||
|
||
#ifndef Animation_h | ||
#define Animation_h | ||
|
||
#import <UIKit/UIKit.h> | ||
#import "ThemeSwitchAnimationModule.h" | ||
|
||
@interface AnimationHelper : NSObject | ||
|
||
+ (void)performFadeAnimation:(UIView *)overlayView | ||
duration:(NSInteger)duration | ||
callback:(void (^)(void))callback; | ||
|
||
+ (void)performCircularAnimation:(UIView *)overlayView | ||
source:(ThemeSwitchAnimationModule *)source | ||
duration:(NSInteger)duration | ||
cxRatio:(CGFloat)cxRatio | ||
cyRatio:(CGFloat)cyRatio | ||
callback:(void (^)(void))callback; | ||
|
||
+ (void)performInvertedCircleAnimation:(UIView *)overlayView | ||
source:(ThemeSwitchAnimationModule *)source | ||
duration:(NSInteger)duration | ||
cxRatio:(CGFloat)cxRatio | ||
cyRatio:(CGFloat)cyRatio | ||
callback:(void (^)(void))callback; | ||
|
||
@end | ||
|
||
#endif /* Animation_h */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
// | ||
// AnimationHelper.m | ||
// react-native-theme-switch-animation | ||
// | ||
// Created by Wadah Esam on 04/11/2023. | ||
// | ||
|
||
|
||
#import "AnimationHelper.h" | ||
|
||
@implementation AnimationHelper | ||
|
||
+ (void)performFadeAnimation:(UIView *)overlayView | ||
duration:(NSInteger)duration | ||
callback:(void (^)(void))callback | ||
{ | ||
[UIView animateWithDuration: duration / 1000.0 | ||
animations:^{ | ||
overlayView.alpha = 0.0; | ||
} | ||
completion:^(BOOL finished){ | ||
if (callback) { | ||
callback(); | ||
} | ||
[overlayView removeFromSuperview]; | ||
}]; | ||
} | ||
|
||
+ (void)performInvertedCircleAnimation:(UIView *)overlayView | ||
source:(ThemeSwitchAnimationModule *)source duration:(NSInteger)duration | ||
cxRatio:(CGFloat)cxRatio | ||
cyRatio:(CGFloat)cyRatio | ||
callback:(void (^__strong)())callback { | ||
|
||
CGFloat width = CGRectGetWidth(overlayView.bounds); | ||
CGFloat height = CGRectGetHeight(overlayView.bounds); | ||
CGPoint center = CGPointMake(width * cxRatio, height * cyRatio); | ||
CGFloat startRadius = [self getPointMaxDistanceInsideContainerWithCx:center.x cy:center.y width:width height:height]; | ||
|
||
|
||
UIBezierPath *startPath = [self generateCircule:startRadius center:center]; | ||
UIBezierPath *endPath = [self generateCircule:0 center:center]; | ||
|
||
|
||
CAShapeLayer *maskLayer = [CAShapeLayer layer]; | ||
maskLayer.path = startPath.CGPath; | ||
overlayView.layer.mask = maskLayer; | ||
|
||
CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; | ||
maskLayerAnimation.fromValue = (__bridge id)(startPath.CGPath); | ||
maskLayerAnimation.toValue = (__bridge id)(endPath.CGPath); | ||
|
||
maskLayerAnimation.duration = duration / 1000.0; | ||
maskLayerAnimation.delegate = source; | ||
maskLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; | ||
maskLayerAnimation.fillMode = kCAFillModeForwards; | ||
maskLayerAnimation.removedOnCompletion = NO; | ||
|
||
|
||
[CATransaction begin]; | ||
[CATransaction setCompletionBlock:^{ | ||
if (callback) { | ||
callback(); | ||
} | ||
maskLayerAnimation.delegate = nil; | ||
}]; | ||
|
||
[maskLayer addAnimation:maskLayerAnimation forKey:@"path"]; | ||
[CATransaction commit]; | ||
} | ||
|
||
+ (void)performCircularAnimation:(UIView *) overlayView | ||
source:(ThemeSwitchAnimationModule *)source | ||
duration:(NSInteger)duration | ||
cxRatio:(CGFloat)cxRatio | ||
cyRatio:(CGFloat)cyRatio | ||
callback:(void (^)(void))callback | ||
{ | ||
double frameDuration = 1.0 / [[UIScreen mainScreen] maximumFramesPerSecond]; | ||
int delayedFrames = 5; | ||
double delayInSeconds = delayedFrames * frameDuration; | ||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); | ||
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ | ||
overlayView.hidden = YES; | ||
UIImage *capturedImageAfterSwitching = [source captureScreen]; | ||
UIImageView *capturedImageViewAfterSwitching = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; | ||
capturedImageViewAfterSwitching.image = capturedImageAfterSwitching; | ||
capturedImageViewAfterSwitching.contentMode = UIViewContentModeScaleAspectFill; | ||
[[UIApplication sharedApplication].keyWindow addSubview:capturedImageViewAfterSwitching]; | ||
overlayView.hidden = NO; | ||
|
||
CGFloat width = CGRectGetWidth(capturedImageViewAfterSwitching.bounds); | ||
CGFloat height = CGRectGetHeight(capturedImageViewAfterSwitching.bounds); | ||
CGPoint center = CGPointMake(width * cxRatio, height * cyRatio); | ||
CGFloat startRadius = [self getPointMaxDistanceInsideContainerWithCx:center.x cy:center.y width:width height:height]; | ||
|
||
UIBezierPath *startPath = [self generateCircule:0 center:center]; | ||
UIBezierPath *endPath = [self generateCircule:startRadius center:center]; | ||
|
||
CAShapeLayer *maskLayer = [CAShapeLayer layer]; | ||
maskLayer.path = startPath.CGPath; | ||
capturedImageViewAfterSwitching.layer.mask = maskLayer; | ||
|
||
CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; | ||
maskLayerAnimation.fromValue = (__bridge id)(startPath.CGPath); | ||
maskLayerAnimation.toValue = (__bridge id)(endPath.CGPath); | ||
maskLayerAnimation.duration = duration / 1000.0; | ||
maskLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; | ||
maskLayerAnimation.fillMode = kCAFillModeForwards; | ||
maskLayerAnimation.removedOnCompletion = NO; | ||
|
||
|
||
[CATransaction begin]; | ||
[CATransaction setCompletionBlock:^{ | ||
if (callback) { | ||
callback(); | ||
} | ||
maskLayerAnimation.delegate = nil; | ||
capturedImageViewAfterSwitching.layer.mask = nil; | ||
capturedImageViewAfterSwitching.hidden = YES; | ||
[capturedImageViewAfterSwitching removeFromSuperview]; | ||
}]; | ||
|
||
[maskLayer addAnimation:maskLayerAnimation forKey:@"path"]; | ||
[CATransaction commit]; | ||
}); | ||
} | ||
|
||
+ (CGFloat)getPointMaxDistanceInsideContainerWithCx:(CGFloat)cx | ||
cy:(CGFloat)cy | ||
width:(CGFloat)width | ||
height:(CGFloat)height | ||
{ | ||
CGFloat topLeftDistance = hypotf(cx, cy); | ||
CGFloat topRightDistance = hypotf(width - cx, cy); | ||
CGFloat bottomLeftDistance = hypotf(cx, height - cy); | ||
CGFloat bottomRightDistance = hypotf(width - cx, height - cy); | ||
return MAX(MAX(topLeftDistance, topRightDistance), MAX(bottomLeftDistance, bottomRightDistance)); | ||
} | ||
|
||
+ (UIBezierPath*) generateCircule:(CGFloat)radius | ||
center:(CGPoint)center | ||
{ | ||
UIBezierPath *circule = [UIBezierPath bezierPathWithArcCenter:center | ||
radius:radius == 0 ? 0.1 : radius // 0 produces weired animation | ||
startAngle:0 | ||
endAngle:M_PI * 2 | ||
clockwise:YES]; | ||
|
||
return circule; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters