Core Animation小记(三)

动画

1.隐式动画。没有制定任何动画的类型叫做隐式动画。事务,是通过CATransaction类来做管理,只能通过+begin和+commit分别来入栈河出栈。任何考验做动画的图层属性都会被添加到栈顶到事务。

CoreAnimation在每个runloop周期中自动开始一次新的事务,任何在一次runloop中属性的改变都会被集中起来,然后做一次0.25秒的动画。

[CATransaction begin];

[CATransaction setAnimationDuration:1.0];

self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];

[CATransaction comit];

UIView的隐式动画:+animateWithDuration:animations:  和 animateWithDuration: animations: completion 可以带入Block便捷使用

2.我们把改变属性时CALayer自动应用的动画称作行为,当CALayer的属性被修改时候,它会调用-actionForKey:方法,传递属性的名称。

图层首先检测它是否有委托,并且是否实现CALayerDelegate协议指定的-actionForLayer:forKey方法。如果有,直接调用并返回结果。

如果没有委托,或者委托没有实现-actionForLayer:forKey方法,图层接着检查包含属性名称对应行为映射的actions字典。

如果actions字典没有包含对应的属性,那么图层接着在它的style字典接着搜索属性名。

最后,如果在style里面也找不到对应的行为,那么图层将会直接调用定义了每个属性的标准行为的-defaultActionForKey:方法。

所以一轮完整的搜索结束之后,-actionForKey:要么返回空(这种情况下将不会有动画发生),要么是CAAction协议对应的对象,最后CALayer拿这个结果去对先前和当前的值做动画。

3.UIKit是如何禁用隐式动画的:每个UIView对它关联的图层都扮演了一个委托,并且提供了-actionForLayer:forKey的实现方法。当不再一个动画块的实现中,UIView对所有图层行为返回nil,但是在动画block内,它返回一个非空值。

4.过渡

过渡并不像属性动画那样平滑地在两个值之间做动画,而是影响到整个图层的变化。过渡动画首先展示之前的图层外观,然后通过一个交换过渡到新的外观。

- (void)viewDidLoad

{

[super viewDidLoad];

//set up images

self.images = @[[UIImage imageNamed:@"Anchor.png"],

[UIImage imageNamed:@"Cone.png"],

[UIImage imageNamed:@"Igloo.png"],

[UIImage imageNamed:@"Spaceship.png"]];

}

- (IBAction)switchImage

{

//set up crossfade transition

CATransition *transition = [CATransition animation];

transition.type = kCATransitionFade;

//apply transition to imageview backing layer

[self.imageView.layer addAnimation:transition forKey:nil];

//cycle to next image

UIImage *currentImage = self.imageView.image;

NSUInteger index = [self.images indexOfObject:currentImage];

index = (index + 1) % [self.images count];

self.imageView.image = self.images[index];

}

UIView +transitionFromView:toView:duration:options:completion:和+transitionWithView:duration:options:animations:方法提供了Core Animation的过渡特性

UIViewAnimationOptionTransitionFlipFromRight         UIViewAnimationOptionTransitionCurlUp                 UIViewAnimationOptionTransitionCurlDown    UIViewAnimationOptionTransitionCrossDissolve UIViewAnimationOptionTransitionFlipFromTop UIViewAnimationOptionTransitionFlipFromBottom

我们对当前视图状态截图,然后在我们改变原始视图的背景色的时候对截图快速转动并且淡出,图8.5展示了我们自定义的过渡效果。

@implementation ViewController

- (IBAction)performTransition

{

//preserve the current view snapshot

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, YES, 0.0);

[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage *coverImage = UIGraphicsGetImageFromCurrentImageContext();

//insert snapshot view in front of this one

UIView *coverView = [[UIImageView alloc] initWithImage:coverImage];

coverView.frame = self.view.bounds;

[self.view addSubview:coverView];

//update the view (we'll simply randomize the layer background color)

CGFloat red = arc4random() / (CGFloat)INT_MAX;

CGFloat green = arc4random() / (CGFloat)INT_MAX;

CGFloat blue = arc4random() / (CGFloat)INT_MAX;

self.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];

//perform animation (anything you like)

[UIView animateWithDuration:1.0 animations:^{

//scale, rotate and fade the view

CGAffineTransform transform = CGAffineTransformMakeScale(0.01, 0.01);

transform = CGAffineTransformRotate(transform, M_PI_2);

coverView.transform = transform;

coverView.alpha = 0.0;

} completion:^(BOOL finished) {

//remove the cover view now we're finished with it

[coverView removeFromSuperview];

}];

}

@end

一般说来,动画在结束之后被自动移除,除非设置removedOnCompletion为NO,如果你设置动画在结束之后不被自动移除,那么当它不需要的时候你要手动移除它;否则它会一直存在于内存中,直到图层被销毁。

5.显式动画

CATransform3D transform = CATransform3DMakeRotation(angle,0,0,1);

CABasicAnimation *animation = [CABasicAnimation animation];

animation.keypath = @"transform";

animation.toValue = [NSValue valueWithCATransform3D:transform];

animation.duration = 0.5;

animation.delegate = self;

[animation setValue:handle forKey:@"handleView"];

[handView.layer addAnimation:animation forKey:nil];

 CABasicAnimation有一个特别的性能:它的KVC可以像一个字典一样,可以用-setValue:forKey:和-valueForKey:来随意设置键值对,即使和你使用的动画类所声明的属性不匹配。

6.关键帧

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,

];

[self.colorLayer addAnimation:animation forKey:nil];

CAKeyframeAnimation有另一种方式去指定动画,就是使用CGPath。path属性可以用一种直观的方式,使用Core Graphics函数定义运动序列来绘制动画。

7.给CAKeyFrameAnimation添加了一个rotationMode的属性。设置它为常量kCAAnimationRotateAuto(清单8.7),图层将会根据曲线的切线自动旋转(图8.2)

8.虚拟属性

可以对transform.rotation关键路径应用动画,而不是transform本身

CABasicAnimation *animation = [CABasicAnimation animation];

animation.keyPath = @"transform.rotation";

animation.duration = 2.0;

animation.byValue = @(M_PI * 2);

[shipLayer addAnimation:animation forKey:nil];

结果运行的特别好,用transform.rotation而不是transform做动画的好处如下:

我们可以不通过关键帧一步旋转多于180度的动画。

可以用相对值而不是绝对值旋转(设置byValue而不是toValue)。

可以不用创建CATransform3D,而是使用一个简单的数值来指定角度。

不会和transform.position或者transform.scale冲突(同样是使用关键路径来做独立的动画属性)。

Core Animation自动地根据通过CAValueFunction来计算的值来更新transform属性。

你可能感兴趣的:(Core Animation小记(三))