1 inline CAAnimation*
2 BounceAnimationElement( CGPoint pFrom, CGPoint pTo, double pBeginTime, double pDuration, CAMediaTimingFunction* pMTF )
3 { CABasicAnimation* v = [ CABasicAnimation animationWithKeyPath:@"position" ];
4 v.fromValue = [ NSValue valueWithCGPoint:pFrom ];
5 v.toValue = [ NSValue valueWithCGPoint:pTo ];
6 v.beginTime = pBeginTime;
7 v.duration = pDuration;
8 v.timingFunction = pMTF;
9 return v;
10 }
11
12 inline CAAnimation*
13 BounceAnimation( CALayer* pL, CGPoint pDest, double pInitialDuration = 1, double pK = .3, size_t pRepeat = 10 )
14 { CAMediaTimingFunction* wMTF_D = [ CAMediaTimingFunction functionWithControlPoints:1./3. :0 :2./3. :1./3. ];
15 CAMediaTimingFunction* wMTF_U = [ CAMediaTimingFunction functionWithControlPoints:1./3. :2./3. :2./3. :1 ];
16
17 CGPoint wOrigin = pL.position;
18
19 NSMutableArray* wAnimationArray = NSMutableArray.array;
20 [ wAnimationArray addObject:BounceAnimationElement( pL.position, pDest, 0, pInitialDuration, wMTF_D ) ];
21
22 double wBeginTime = pInitialDuration;
23
24 double wK = 1;
25 while ( pRepeat-- )
26 { wK *= pK;
27 CGPoint wPoint = CGPointMake
28 ( wOrigin.x * wK + pDest.x * ( 1 - wK )
29 , wOrigin.y * wK + pDest.y * ( 1 - wK )
30 );
31 double wDuration = pInitialDuration * wK * ( 1 / sqrt( wK ) );
32 [ wAnimationArray addObject:BounceAnimationElement( pDest, wPoint, wBeginTime, wDuration, wMTF_U ) ];
33 wBeginTime += wDuration;
34 [ wAnimationArray addObject:BounceAnimationElement( wPoint, pDest, wBeginTime, wDuration, wMTF_D ) ];
35 wBeginTime += wDuration;
36 }
37
38 pL.position = pDest;
39
40 CAAnimationGroup* v = CAAnimationGroup.animation;
41 v.duration = wBeginTime;
42 v.animations = wAnimationArray;
43
44 return v;
45 }
46
47 - (IBAction)
48 Group
49 { [ mL addAnimation:BounceAnimation( mL, CGPointMake( 160, 240 ) ) forKey:nil ];
50 }
51