Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define kANIMATION_IMAGE_TAG 2049
- @property (copy, nonatomic) void (^completionBlock)(UIImage *);
- @property (strong, nonatomic) UIView *animationParent;
- - (void)flyImageFrom:(UIImageView *)imageViewA toRect:(CGRect)rect insideParentView:(UIView *)parent completion:(void (^)(UIImage *))completion {
- self.completionBlock = completion;
- if (!self.animationParent) self.animationParent = imageViewA.superview;
- UIImageView *animationView = [[UIImageView alloc] initWithImage:imageViewA.image];
- animationView.tag = kANIMATION_IMAGE_TAG;
- animationView.frame = imageViewA.frame;
- [self.animationParent addSubview:animationView];
- // scale
- CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
- [resizeAnimation setFromValue:[NSValue valueWithCGSize:imageViewA.bounds.size]];
- [resizeAnimation setToValue:[NSValue valueWithCGSize:rect.size]];
- // build the path
- CGRect aRect = [imageViewA convertRect:imageViewA.bounds toView:self.animationParent];
- CGRect bRect = rect;
- CGFloat startX = aRect.origin.x + aRect.size.width / 2.0;
- CGFloat startY = aRect.origin.y + aRect.size.height / 2.0;
- CGFloat endX = bRect.origin.x + bRect.size.width / 2.0;
- CGFloat endY = bRect.origin.y + bRect.size.height / 2.0;
- CGPoint start = CGPointMake(startX, startY);
- CGPoint end = CGPointMake(endX, endY);
- // come up with a reasonable speed, 400px per second
- CGFloat distance = [self distanceFrom:start to:end];
- CGFloat duration = MIN(MAX(distance / 400.0, 0.3), 0.6);
- // calculate control points
- CGPoint cp0 = [self controlPointAt:0.333 fromPoint:start toPoint:end];
- CGPoint cp1 = [self controlPointAt:0.666 fromPoint:start toPoint:end];
- CGMutablePathRef path = CGPathCreateMutable();
- CGPathMoveToPoint(path, NULL, startX, startY);
- CGPathAddCurveToPoint(path, NULL, cp0.x, cp0.y, cp1.x, cp1.y, endX, endY);
- // keyframe animation
- CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
- keyframeAnimation.calculationMode = kCAAnimationPaced;
- keyframeAnimation.fillMode = kCAFillModeForwards;
- keyframeAnimation.removedOnCompletion = NO;
- keyframeAnimation.path = path;
- CGPathRelease(path);
- CAAnimationGroup *group = [CAAnimationGroup animation];
- group.fillMode = kCAFillModeForwards;
- group.removedOnCompletion = NO;
- [group setAnimations:[NSArray arrayWithObjects:keyframeAnimation, resizeAnimation, nil]];
- group.duration = duration;
- group.delegate = self;
- [group setValue:animationView forKey:@"animationView"];
- [animationView.layer addAnimation:group forKey:@"animationGroup"];
- }
- - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
- if (self.completionBlock) {
- self.completionBlock(animationView.image);
- }
- UIImageView *animationView = (UIImageView *)[self.animationParent viewWithTag:kANIMATION_IMAGE_TAG];
- [animationView removeFromSuperview];
- }
- // the following methods compute control points for the curved path the image will take.
- // you can opt to put these in some "math class" and make them public class methods
- - (CGFloat)angleBetweenOrigin:(CGPoint)o andPoint:(CGPoint)p {
- CGFloat deltaX = p.x - o.x;
- CGFloat deltaY = o.y - p.y;
- return atan2f(deltaY, deltaX);
- }
- - (CGPoint)pointAtDistance:(CGFloat)deflection fromBase:(CGPoint)basePoint normalTo:(CGPoint)normalSegment {
- CGFloat complement = [self angleBetweenOrigin:basePoint andPoint:normalSegment];
- CGFloat angle = M_PI_2 - complement;
- CGFloat dx = deflection * cosf(angle);
- CGFloat dy = deflection * sinf(angle);
- return CGPointMake(basePoint.x + dx, basePoint.y + dy);
- }
- - (CGFloat)distanceFrom:(CGPoint)a to:(CGPoint)b {
- CGFloat deltaX = b.x - a.x;
- CGFloat deltaY = b.y - a.y;
- return sqrtf(deltaX*deltaX + deltaY*deltaY);
- }
- - (CGPoint)controlPointAt:(CGFloat)progress fromPoint:(CGPoint)start toPoint:(CGPoint)end {
- CGFloat deltaX = end.x - start.x;
- CGFloat deltaY = end.y - start.y;
- CGFloat len = sqrtf(deltaX*deltaX + deltaY*deltaY);
- CGFloat deflection = len * 0.3;
- CGFloat baseX = start.x + progress*deltaX;
- CGFloat baseY = start.y + progress*deltaY;
- CGPoint base = CGPointMake(baseX, baseY);
- return [self pointAtDistance:deflection fromBase:base normalTo:start];
- }
Advertisement
Add Comment
Please, Sign In to add comment