CALayer动画专题
来自《ios核心动画高级技巧》书中的一些例子总结,包含了
- 隐式动画
- 显式动画
- 缓冲-动画速度变化函数
https://zsisme.gitbooks.io/ios-/content/chapter7/transactions.html
隐式动画
当你改变CALayer的一个可做动画的属性,它并不能立刻在屏幕上体现出来。相反,它是从先前的值平滑过渡到新的值。这一切都是默认的行为,你不需要做额外的操作。
隐式动画通过改变layer的backgroundColor实现颜色渐变的动画
//randomize the layer background color
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor; ```
#### 隐式动画的事务
`CATransaction` 可以
- 设置动画的时间
- 设置是否开启隐式动画
- 其他
```objc
//begin a new transaction
[CATransaction begin];
//set the animation duration to 1 second
[CATransaction setAnimationDuration:1.0];
//randomize the layer background color
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
//commit the transaction
[CATransaction commit];
事务的完成block
//add the spin animation on completion
[CATransaction setCompletionBlock:^{
//rotate the layer 90 degrees
CGAffineTransform transform = self.colorLayer.affineTransform;
transform = CGAffineTransformRotate(transform, M_PI_2);
self.colorLayer.affineTransform = transform;
}];
view关联的layer禁用了隐式动画
默认的view中关联的View禁用了layer的隐式动画,一种简单的方式是设置action来达到隐式动画的效果
//begin a new transaction
[CATransaction begin];
//set the animation duration to 1 second
[CATransaction setAnimationDuration:1.0];
//randomize the layer background color
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.layerView.layer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
//commit the transaction
[CATransaction commit];
图层颜色瞬间切换到新的值,而不是之前平滑过渡的动画。
可以设置默认隐式动画的行为,如下设置了关闭隐式动画,在非view关联的layer上也不会有隐式动画的行为了
[CATransaction setDisableActions:YES];
自定义隐式动画的行为
view关联的layer可以通过设置action来实现隐式动画
//add a custom action
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
self.colorLayer.actions = @{@"backgroundColor": transition};
//add it to our view
[self.layerView.layer addSublayer:self.colorLayer];
显式动画
显式的调用 CALayer
的方法 addAnimation
执行动画效果
颜色变换帧动画:
//create a keyframe animation
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"backgroundColor";
animation.duration = 2.0;
animation.values = @[
(__bridge id)[UIColor blueColor].CGColor,
(__bridge id)[UIColor redColor].CGColor,
(__bridge id)[UIColor greenColor].CGColor,
(__bridge id)[UIColor blueColor].CGColor ];
//apply animation to layer
[self.colorLayer addAnimation:animation forKey:nil];
路径帧动画:
//create a path
UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
[bezierPath moveToPoint:CGPointMake(0, 150)];
[bezierPath addCurveToPoint:CGPointMake(300, 150) controlPoint1:CGPointMake(75, 0) controlPoint2:CGPointMake(225, 300)];
//add the ship
CALayer *shipLayer = [CALayer layer];
shipLayer.frame = CGRectMake(0, 0, 64, 64);
shipLayer.position = CGPointMake(0, 150);
shipLayer.contents = (__bridge id)[UIImage imageNamed: @"Ship.png"].CGImage;
[self.containerView.layer addSublayer:shipLayer];
//create the keyframe animation
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
animation.duration = 4.0;
animation.path = bezierPath.CGPath;
[shipLayer addAnimation:animation forKey:nil];
旋转动画:
//animate the ship rotation
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"transform.rotation";
animation.duration = 2.0;
animation.byValue = @(M_PI * 2);
[shipLayer addAnimation:animation forKey:nil];
动画组
CAAnimationGroup
可以把这些动画组合在一起。
//create a path
UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
[bezierPath moveToPoint:CGPointMake(0, 150)];
[bezierPath addCurveToPoint:CGPointMake(300, 150) controlPoint1:CGPointMake(75, 0) controlPoint2:CGPointMake(225, 300)];
//draw the path using a CAShapeLayer
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.path = bezierPath.CGPath;
pathLayer.fillColor = [UIColor clearColor].CGColor;
pathLayer.strokeColor = [UIColor redColor].CGColor;
pathLayer.lineWidth = 3.0f;
[self.containerView.layer addSublayer:pathLayer];
//add a colored layer
CALayer *colorLayer = [CALayer layer];
colorLayer.frame = CGRectMake(0, 0, 64, 64);
colorLayer.position = CGPointMake(0, 150);
colorLayer.backgroundColor = [UIColor greenColor].CGColor;
[self.containerView.layer addSublayer:colorLayer];
//create the position animation
CAKeyframeAnimation *animation1 = [CAKeyframeAnimation animation];
animation1.keyPath = @"position";
animation1.path = bezierPath.CGPath;
animation1.rotationMode = kCAAnimationRotateAuto;
//create the color animation
CABasicAnimation *animation2 = [CABasicAnimation animation];
animation2.keyPath = @"backgroundColor";
animation2.toValue = (__bridge id)[UIColor redColor].CGColor;
//create group animation
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.animations = @[animation1, animation2];
groupAnimation.duration = 4.0;
//add the animation to the color layer
[colorLayer addAnimation:groupAnimation forKey:nil];
缓冲-动画速度变化函数
动画速度
- Layer 计时函数:
这里有一些方式来创建CAMediaTimingFunction,最简单的方式是调用+timingFunctionWithName:的构造方法。这里传入如下几个常量之一:
kCAMediaTimingFunctionLinear //先行匀速
kCAMediaTimingFunctionEaseIn //加速
kCAMediaTimingFunctionEaseOut //减速
kCAMediaTimingFunctionEaseInEaseOut //加速然后减速
kCAMediaTimingFunctionDefault //默认行为,和kCAMediaTimingFunctionEaseInEaseOut相似
//configure the transaction
[CATransaction begin];
[CATransaction setAnimationDuration:1.0];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
//set the position
self.colorLayer.position = [[touches anyObject] locationInView:self.view];
//commit transaction
[CATransaction commit];
- UIView 计时函数
UIKit的动画也同样支持这些缓冲方法的使用,尽管语法和常量有些不同,为了改变UIView动画的缓冲选项,给options参数添加如下常量之一:
UIViewAnimationOptionCurveEaseInOut
UIViewAnimationOptionCurveEaseIn
UIViewAnimationOptionCurveEaseOut
UIViewAnimationOptionCurveLinear
UIView 动画指定计时函数选项
//perform the animation
[UIView animateWithDuration:1.0 delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
//set the position
self.colorView.center = [[touches anyObject] locationInView:self.view];
}
completion:NULL];
计时函数和关键帧动画
CAKeyframeAnimation有一个NSArray类型的timingFunctions属性,我们可以用它来对每次动画的步骤指定不同的计时函数。但是指定函数的个数一定要等于keyframes数组的元素个数减一,因为它是描述每一帧之间动画速度的函数。
//create a keyframe animation
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"backgroundColor";
animation.duration = 2.0;
animation.values = @[
(__bridge id)[UIColor blueColor].CGColor,
(__bridge id)[UIColor redColor].CGColor,
(__bridge id)[UIColor greenColor].CGColor,
(__bridge id)[UIColor blueColor].CGColor ];
//add timing function
CAMediaTimingFunction *fn = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn];
animation.timingFunctions = @[fn, fn, fn];
//apply animation to layer
[self.colorLayer addAnimation:animation forKey:nil];