CABasicAnimation已经可以应付一些比较简单的应用场景了,比如view的平移出现、淡入淡出等。但是在有些情况下直线的运动并不能满足我们的需要,因此有必要学习进阶版的核心动画,那就是CAKeyFrameAnimation
CABasicAnimation算是CAKeyFrameAnimation的特殊情况,即不考虑中间变换过程,只考虑起始点与目标点就可以了。而CAKeyFrameAnimation则更复杂一些,允许我们在起点与终点间自定义更多内容来达到我们的实际应用需求
CALayer * rectLayer = [[CALayeralloc] init];
rectLayer.frame = CGRectMake(15, 200, 30, 30);
rectLayer.cornerRadius = 15;
rectLayer.backgroundColor = [[UIColorblackColor] CGColor];
[self.view.layeraddSublayer:rectLayer];
CAKeyframeAnimation *rectRunAnimation = [CAKeyframeAnimationanimationWithKeyPath:@"position"];
//设定关键帧位置,必须含起始与终止位置
rectRunAnimation.values = @[[NSValue valueWithCGPoint:rectLayer.frame.origin],
[NSValuevalueWithCGPoint:CGPointMake(320 -15,
rectLayer.frame.origin.y)],
[NSValuevalueWithCGPoint:CGPointMake(320 -15,
rectLayer.frame.origin.y + 100)],
[NSValuevalueWithCGPoint:CGPointMake(15, rectLayer.frame.origin.y + 100)],
[NSValuevalueWithCGPoint:rectLayer.frame.origin]];
//设定每个关键帧的时长,如果没有显式地设置,则默认每个帧的时间=总duration/(values.count - 1)
rectRunAnimation.keyTimes = @[[NSNumber numberWithFloat:0.0], [NSNumbernumberWithFloat:0.6],
[NSNumbernumberWithFloat:0.7], [NSNumbernumberWithFloat:0.8],
[NSNumbernumberWithFloat:1]];
rectRunAnimation.timingFunctions =@[[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionLinear],
[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionLinear],
[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionLinear]];
rectRunAnimation.repeatCount = 1000;
rectRunAnimation.autoreverses = NO;
rectRunAnimation.calculationMode =kCAAnimationLinear;
rectRunAnimation.duration = 4;
[rectLayer addAnimation:rectRunAnimationforKey:@"rectRunAnimation"];
values属性
values属性指明整个动画过程中的关键帧点,例如上例中的矩形 顶点滑动轨迹 A-E就是通过values指定的。需要注意的是,起点必须作为values的第一个值。
path属性
作用与values属性一样,同样是用于指定整个动画所经过的路径的。需要注意的是,values与path是互斥的,当values与path同时指定时,path会覆盖values,即values属性将被忽略。例如上述例子等价于代码中values方式的path设置方式为:
//等价于 values的写法 互斥 写一即可
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, rectLayer.position.x -15, rectLayer.position.y -15);
CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y);
CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y +100);
CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y +100);
CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y);
rectRunAnimation.path = path;
CGPathRelease(path);
keyTimes属性
该属性是一个数组,用以指定每个子路径(AB,BC,CD)的时间。如果你没有显式地对keyTimes进行设置,则系统会默认每条子路径的时间为:ti=duration/(5-1),即每条子路径的duration相等,都为duration的1\4。当然,我们也可以传个数组让物体快慢结合。例如,你可以传入{0.0, 0.1,0.6,0.7,1.0},其中首尾必须分别是0和1,因此tAB=0.1-0, tCB=0.6-0.1, tDC=0.7-0.6, tED=1-0.7.....
timeFunctions属性
这是一个数组,你有几个子路径就应该传入几个元素
kCAMediaTimingFunctionLinear//线性
kCAMediaTimingFunctionEaseIn//淡入
kCAMediaTimingFunctionEaseOut//淡出
kCAMediaTimingFunctionEaseInEaseOut//淡入淡出
kCAMediaTimingFunctionDefault//默认
calculationMode属性
const kCAAnimationLinear//线性,默认
const kCAAnimationDiscrete//离散,无中间过程,但keyTimes设置的时间依旧生效,物体跳跃地出现在各个关键帧上
const kCAAnimationPaced//平均,keyTimes跟timeFunctions失效
const kCAAnimationCubic//平均,同上
const kCAAnimationCubicPaced//平均,同上
-(void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}