Guest User

Untitled

a guest
Feb 7th, 2013
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.51 KB | None | 0 0
  1.  
  2. #define kANIMATION_IMAGE_TAG 2049
  3.  
  4. @property (copy, nonatomic) void (^completionBlock)(UIImage *);
  5. @property (strong, nonatomic) UIView *animationParent;
  6.  
  7. - (void)flyImageFrom:(UIImageView *)imageViewA toRect:(CGRect)rect insideParentView:(UIView *)parent completion:(void (^)(UIImage *))completion {
  8.  
  9. self.completionBlock = completion;
  10. if (!self.animationParent) self.animationParent = imageViewA.superview;
  11.  
  12. UIImageView *animationView = [[UIImageView alloc] initWithImage:imageViewA.image];
  13. animationView.tag = kANIMATION_IMAGE_TAG;
  14. animationView.frame = imageViewA.frame;
  15. [self.animationParent addSubview:animationView];
  16.  
  17. // scale
  18. CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
  19. [resizeAnimation setFromValue:[NSValue valueWithCGSize:imageViewA.bounds.size]];
  20. [resizeAnimation setToValue:[NSValue valueWithCGSize:rect.size]];
  21.  
  22. // build the path
  23. CGRect aRect = [imageViewA convertRect:imageViewA.bounds toView:self.animationParent];
  24. CGRect bRect = rect;
  25.  
  26. CGFloat startX = aRect.origin.x + aRect.size.width / 2.0;
  27. CGFloat startY = aRect.origin.y + aRect.size.height / 2.0;
  28. CGFloat endX = bRect.origin.x + bRect.size.width / 2.0;
  29. CGFloat endY = bRect.origin.y + bRect.size.height / 2.0;
  30.  
  31. CGPoint start = CGPointMake(startX, startY);
  32. CGPoint end = CGPointMake(endX, endY);
  33.  
  34. // come up with a reasonable speed, 400px per second
  35. CGFloat distance = [self distanceFrom:start to:end];
  36. CGFloat duration = MIN(MAX(distance / 400.0, 0.3), 0.6);
  37.  
  38. // calculate control points
  39. CGPoint cp0 = [self controlPointAt:0.333 fromPoint:start toPoint:end];
  40. CGPoint cp1 = [self controlPointAt:0.666 fromPoint:start toPoint:end];
  41.  
  42. CGMutablePathRef path = CGPathCreateMutable();
  43. CGPathMoveToPoint(path, NULL, startX, startY);
  44. CGPathAddCurveToPoint(path, NULL, cp0.x, cp0.y, cp1.x, cp1.y, endX, endY);
  45.  
  46. // keyframe animation
  47. CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
  48. keyframeAnimation.calculationMode = kCAAnimationPaced;
  49. keyframeAnimation.fillMode = kCAFillModeForwards;
  50. keyframeAnimation.removedOnCompletion = NO;
  51. keyframeAnimation.path = path;
  52. CGPathRelease(path);
  53.  
  54. CAAnimationGroup *group = [CAAnimationGroup animation];
  55. group.fillMode = kCAFillModeForwards;
  56. group.removedOnCompletion = NO;
  57. [group setAnimations:[NSArray arrayWithObjects:keyframeAnimation, resizeAnimation, nil]];
  58. group.duration = duration;
  59. group.delegate = self;
  60.  
  61. [group setValue:animationView forKey:@"animationView"];
  62. [animationView.layer addAnimation:group forKey:@"animationGroup"];
  63. }
  64.  
  65.  
  66. - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
  67.  
  68. if (self.completionBlock) {
  69. self.completionBlock(animationView.image);
  70. }
  71.  
  72. UIImageView *animationView = (UIImageView *)[self.animationParent viewWithTag:kANIMATION_IMAGE_TAG];
  73. [animationView removeFromSuperview];
  74. }
  75.  
  76. // the following methods compute control points for the curved path the image will take.
  77. // you can opt to put these in some "math class" and make them public class methods
  78.  
  79. - (CGFloat)angleBetweenOrigin:(CGPoint)o andPoint:(CGPoint)p {
  80.  
  81. CGFloat deltaX = p.x - o.x;
  82. CGFloat deltaY = o.y - p.y;
  83.  
  84. return atan2f(deltaY, deltaX);
  85. }
  86.  
  87. - (CGPoint)pointAtDistance:(CGFloat)deflection fromBase:(CGPoint)basePoint normalTo:(CGPoint)normalSegment {
  88.  
  89. CGFloat complement = [self angleBetweenOrigin:basePoint andPoint:normalSegment];
  90. CGFloat angle = M_PI_2 - complement;
  91.  
  92. CGFloat dx = deflection * cosf(angle);
  93. CGFloat dy = deflection * sinf(angle);
  94. return CGPointMake(basePoint.x + dx, basePoint.y + dy);
  95. }
  96.  
  97. - (CGFloat)distanceFrom:(CGPoint)a to:(CGPoint)b {
  98.  
  99. CGFloat deltaX = b.x - a.x;
  100. CGFloat deltaY = b.y - a.y;
  101.  
  102. return sqrtf(deltaX*deltaX + deltaY*deltaY);
  103. }
  104.  
  105. - (CGPoint)controlPointAt:(CGFloat)progress fromPoint:(CGPoint)start toPoint:(CGPoint)end {
  106.  
  107. CGFloat deltaX = end.x - start.x;
  108. CGFloat deltaY = end.y - start.y;
  109.  
  110. CGFloat len = sqrtf(deltaX*deltaX + deltaY*deltaY);
  111. CGFloat deflection = len * 0.3;
  112.  
  113. CGFloat baseX = start.x + progress*deltaX;
  114. CGFloat baseY = start.y + progress*deltaY;
  115. CGPoint base = CGPointMake(baseX, baseY);
  116.  
  117. return [self pointAtDistance:deflection fromBase:base normalTo:start];
  118. }
Advertisement
Add Comment
Please, Sign In to add comment