对我们的弹性球来说,我们可以使用bounceEaseOut函数:

 1 float bounceEaseOut(float t)
 2 {
 3     if (t < 4/11.0) {
 4         return (121 * t * t)/16.0;
 5     } else if (t < 8/11.0) {
 6         return (363/40.0 * t * t) - (99/10.0 * t) + 17/5.0;
 7     } else if (t < 9/10.0) {
 8         return (4356/361.0 * t * t) - (35442/1805.0 * t) + 16061/1805.0;
 9     }
10     return (54/5.0 * t * t) - (513/25.0 * t) + 268/25.0;
11 }

如果修改清单10.7的代码来引入bounceEaseOut方法,我们的任务就是仅仅交换缓冲函数,现在就可以选择任意的缓冲类型创建动画了(见清单10.8)。

清单10.8 用关键帧实现自定义的缓冲函数

 1 - (void)animate
 2 {
 3     //reset ball to top of screen
 4     self.ballView.center = CGPointMake(150, 32);
 5     //set up animation parameters
 6     NSValue *fromValue = [NSValue valueWithCGPoint:CGPointMake(150, 32)];
 7     NSValue *toValue = [NSValue valueWithCGPoint:CGPointMake(150, 268)];
 8     CFTimeInterval duration = 1.0;
 9     //generate keyframes
10     NSInteger numFrames = duration * 60;
11     NSMutableArray *frames = [NSMutableArray array];
12     for (int i = 0; i < numFrames; i++) {
13         float time = 1/(float)numFrames * i;
14         //apply easing
15         time = bounceEaseOut(time);
16         //add keyframe
17         [frames addObject:[self interpolateFromValue:fromValue toValue:toValue time:time]];
18     }
19     //create keyframe animation
20     CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
21     animation.keyPath = @"position";
22     animation.duration = 1.0;
23     animation.delegate = self;
24     animation.values = frames;
25     //apply animation
26     [self.ballView.layer addAnimation:animation forKey:nil];
27 }