1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-03 09:57:46 +01:00
Telegram/Telegraph/TGMediaAvatarEditorTransition.m
2016-02-25 01:03:51 +01:00

232 lines
9.3 KiB
Objective-C

#import "TGMediaAvatarEditorTransition.h"
#import "TGPhotoEditorController.h"
#import "TGModernGalleryTransitionView.h"
#import "TGImageView.h"
#import "TGPhotoEditorUtils.h"
#import "TGImageUtils.h"
#import "JNWSpringAnimation.h"
#import "TGAnimationBlockDelegate.h"
#import "TGPhotoEditorTabController.h"
#import "TGPhotoAvatarCropView.h"
@interface TGMediaAvatarEditorTransition ()
{
__weak TGPhotoEditorController *_controller;
UIView *_curtainView;
UIImageView *_fromTransitionView;
TGImageView *_toTransitionView;
}
@end
@implementation TGMediaAvatarEditorTransition
- (instancetype)initWithController:(TGPhotoEditorController *)controller fromView:(UIView *)fromView
{
self = [super init];
if (self != nil)
{
_controller = controller;
_fromTransitionView = [[UIImageView alloc] init];
if ([fromView conformsToProtocol:@protocol(TGModernGalleryTransitionView)])
{
id<TGModernGalleryTransitionView> transitionView = (id<TGModernGalleryTransitionView>)fromView;
_fromTransitionView.image = [transitionView transitionImage];
}
}
return self;
}
- (void)presentAnimated:(bool)__unused animated
{
_controller.view.backgroundColor = [UIColor clearColor];
UIView *transitionWrapperView = [_controller transitionWrapperView];
_curtainView = [[UIView alloc] initWithFrame:transitionWrapperView.frame];
_curtainView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_curtainView.alpha = 0.0f;
_curtainView.backgroundColor = [UIColor blackColor];
[transitionWrapperView addSubview:_curtainView];
CGRect referenceFrame = self.referenceFrame();
_fromTransitionView.frame = [transitionWrapperView convertRect:referenceFrame fromView:nil];
[transitionWrapperView addSubview:_fromTransitionView];
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if ([_controller inFormSheet] || [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
orientation = UIInterfaceOrientationPortrait;
CGSize referenceViewSize = [_controller referenceViewSizeForOrientation:orientation];
CGRect containerFrame = [TGPhotoEditorTabController photoContainerFrameForParentViewFrame:CGRectMake(0, 0, referenceViewSize.width, referenceViewSize.height) toolbarLandscapeSize:_controller.toolbarLandscapeSize orientation:orientation includePanel:true];
CGFloat shortSide = MIN(referenceViewSize.width, referenceViewSize.height);
CGFloat diameter = shortSide - [TGPhotoAvatarCropView areaInsetSize].width * 2;
CGSize referenceImageSize = self.referenceImageSize();
CGSize fittedSize = TGScaleToFill(referenceImageSize, CGSizeMake(diameter, diameter));
CGRect fromTransitionFrame = CGRectMake(containerFrame.origin.x + (containerFrame.size.width - fittedSize.width) / 2, containerFrame.origin.y + (containerFrame.size.height - fittedSize.height) / 2, fittedSize.width, fittedSize.height);
[self animateView:_fromTransitionView frameFrom:_fromTransitionView.frame to:[_controller.view convertRect:fromTransitionFrame toView:transitionWrapperView] velocity:CGPointZero rotationFrom:0.0f to:0.0f animatingIn:true completion:^(__unused bool finished)
{
}];
_toTransitionView = [[TGImageView alloc] initWithFrame:fromTransitionFrame];
[_toTransitionView setSignal:[[[self.referenceScreenImageSignal() deliverOn:[SQueue mainQueue]] filter:^bool(id result)
{
return [result isKindOfClass:[UIImage class]];
}] onNext:^(UIImage *next)
{
[_controller _setScreenImage:next];
}]];
[transitionWrapperView addSubview:_toTransitionView];
CGSize toSize = TGScaleToFill(referenceImageSize, referenceFrame.size);
CGRect fromFrame = CGRectMake(referenceFrame.origin.x + (referenceFrame.size.width - toSize.width) / 2.0f, referenceFrame.origin.y + (referenceFrame.size.height - toSize.height) / 2, toSize.width, toSize.height);
fromFrame = [_controller.view convertRect:fromFrame fromView:nil];
[self animateView:_toTransitionView frameFrom:fromFrame to:_toTransitionView.frame velocity:CGPointZero rotationFrom:0.0f to:0.0f animatingIn:true completion:^(bool __unused finished)
{
_controller.view.backgroundColor = [UIColor blackColor];
_curtainView.hidden = true;
_fromTransitionView.hidden = true;
[_toTransitionView removeFromSuperview];
_toTransitionView = nil;
[_controller _finishedTransitionIn];
}];
_toTransitionView.alpha = 0.0f;
[UIView animateWithDuration:0.07 animations:^
{
_toTransitionView.alpha = 1.0f;
}];
[UIView animateWithDuration:0.3 animations:^
{
_curtainView.alpha = 1.0f;
}];
}
- (void)dismissAnimated:(bool)__unused animated completion:(void (^)(void))completion
{
_controller.view.backgroundColor = [UIColor clearColor];
_curtainView.hidden = false;
UIView *transitionWrapperView = [_controller transitionWrapperView];
UIView *fromView = self.repView;
CGRect outReferenceFrame = self.outReferenceFrame;
fromView.frame = [transitionWrapperView convertRect:outReferenceFrame fromView:nil];
[transitionWrapperView addSubview:fromView];
CGRect toFrame = self.referenceFrame();
[self animateView:fromView frameFrom:fromView.frame to:toFrame velocity:CGPointZero rotationFrom:0.0f to:0.0f animatingIn:false completion:^(__unused bool finished)
{
[fromView removeFromSuperview];
}];
UIView *toView = _fromTransitionView;
toView.hidden = false;
toView.frame = outReferenceFrame;
[self animateView:toView frameFrom:toView.frame to:toFrame velocity:CGPointZero rotationFrom:0.0f to:0.0f animatingIn:false completion:^(__unused bool finished)
{
if (completion != nil)
completion();
[toView removeFromSuperview];
}];
[UIView animateWithDuration:0.1 animations:^
{
fromView.alpha = 0.0f;
}];
[UIView animateWithDuration:0.3f animations:^
{
_curtainView.alpha = 0.0f;
} completion:^(__unused BOOL finished)
{
}];
}
- (void)animateView:(UIView *)view frameFrom:(CGRect)fromFrame to:(CGRect)toFrame velocity:(CGPoint)__unused velocity rotationFrom:(CGFloat)fromRotation to:(CGFloat)toRotation animatingIn:(bool)animatingIn completion:(void (^)(bool))completion
{
if (fromFrame.size.width < FLT_EPSILON || fromFrame.size.height < FLT_EPSILON )
{
completion(true);
return;
}
if (ABS(toRotation - fromRotation) > FLT_EPSILON)
{
}
[CATransaction begin];
CGFloat damping = animatingIn ? 25.0f : 30.0f;
CGFloat mass = 0.8f;
CGFloat durationFactor = animatingIn ? 1.8f : 2.0f;
CGPoint fromPosition = CGPointMake(CGRectGetMidX(fromFrame), CGRectGetMidY(fromFrame));
CGPoint toPosition = CGPointMake(CGRectGetMidX(toFrame), CGRectGetMidY(toFrame));
JNWSpringAnimation *positionAnimation = [JNWSpringAnimation animationWithKeyPath:@"position"];
positionAnimation.fromValue = [NSValue valueWithCGPoint:fromPosition];
positionAnimation.toValue = [NSValue valueWithCGPoint:toPosition];
positionAnimation.damping = damping;
positionAnimation.mass = mass;
positionAnimation.removedOnCompletion = true;
positionAnimation.fillMode = kCAFillModeForwards;
positionAnimation.durationFactor = durationFactor;
TGAnimationBlockDelegate *delegate = [[TGAnimationBlockDelegate alloc] initWithLayer:view.layer];
delegate.completion = ^(BOOL finished)
{
if (completion)
completion(finished);
};
positionAnimation.delegate = delegate;
view.layer.position = toPosition;
[view.layer addAnimation:positionAnimation forKey:@"position"];
CGPoint fromScale = CGPointMake(fromFrame.size.width / view.bounds.size.width, fromFrame.size.height/ view.bounds.size.height);
CGPoint toScale = CGPointMake(toFrame.size.width / view.bounds.size.width, toFrame.size.height / view.bounds.size.height);
view.layer.transform = CATransform3DMakeScale(toFrame.size.width / view.bounds.size.width, toFrame.size.height / view.bounds.size.height, 1.0f);
{
JNWSpringAnimation *scaleAnimation = [JNWSpringAnimation animationWithKeyPath:@"transform.scale.x"];
scaleAnimation.fromValue = @(fromScale.x);
scaleAnimation.toValue = @(toScale.x);
scaleAnimation.damping = damping;
scaleAnimation.mass = mass;
scaleAnimation.removedOnCompletion = true;
scaleAnimation.fillMode = kCAFillModeForwards;
scaleAnimation.durationFactor = durationFactor;
[view.layer addAnimation:scaleAnimation forKey:@"transform.scale.x"];
}
{
JNWSpringAnimation *scaleAnimation = [JNWSpringAnimation animationWithKeyPath:@"transform.scale.y"];
scaleAnimation.fromValue = @(fromScale.y);
scaleAnimation.toValue = @(toScale.y);
scaleAnimation.damping = damping;
scaleAnimation.mass = mass;
scaleAnimation.removedOnCompletion = true;
scaleAnimation.fillMode = kCAFillModeForwards;
scaleAnimation.durationFactor = durationFactor;
[view.layer addAnimation:scaleAnimation forKey:@"transform.scale.y"];
}
[CATransaction commit];
}
@end