动画

CoreAnimtion 基础

2016-01-07  本文已影响40人  张无忌_

CoreAnimation是一组非常强大 的API,它可以做出来非常绚丽的动画效果,前边介绍了 CoreAnimation 的核心组件CALayer

CAAnimation简介:是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类;

常用的属性:

属性说明:(红色代表来自CAMediaTiming协议的属性)

duration:动画的持续时间

repeatCount:重复次数,无限循环可以设置HUGE_VALF或者MAXFLOAT

repeatDuration:重复时间

removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards

fillMode:决定当前对象在非active时间段的行为。比如动画开始之前或者动画结束之后

beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间

timingFunction:速度控制函数,控制动画运行的节奏

delegate:动画代理

话不多说,上代码:

// 1. 初始化动画对象  基本动画

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];

// 设置代理

anim.delegate = self;

// 2. 设置动画属性

[anim setToValue:[NSValue valueWithCGPoint:toValue]];

[anim setDuration:1.0f];

// 4. 添加动画到图层

[self.myView.layer addAnimation:anim forKey:nil];

点击屏幕,动画执行完成,后又返回初始位置,怎么能让动画停留在最后点击位置呢? 这时候     fillMode    跟 removedOnCompletion  就派上用场了;

anim.fillMode = kCAFillModeForwards; //逐渐逼近目标点

 anim.removedOnCompletion = NO;

fillMode属性值(要想fillMode有效,最好设置removedOnCompletion = NO)

kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态

kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态

kCAFillModeBackwards 在动画开始前,只需要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始。

kCAFillModeBoth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态

设置完之后,在运行,发现myView可以停留在手指点击后的位置了。  但是 很奇怪,  view的Frame没有任何变化  ,可以用

 NSLog(@"%@",NSStringFromCGRect(self.myView.frame));  

在动画结束后,打印view的Frame观察

想要解决这个问题,可以使用setValue:forKey:传值

[anim setValue:[NSValue valueWithCGPoint:toValue] forKey:@"targetPoint1"];

[anim setValue:@"translationTo" forKey:@"animationType"];

然后在- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 中设置 value的cener属性,修改坐标。

CGPoint targetPoint = [[anim valueForKey:@"targetPoint1"] CGPointValue];

NSLog(@"tragetPoint:%@",NSStringFromCGPoint(targetPoint));

完之后,在观察view的frame,  完美解决;

起始UIView帮我们封装了CoreAnimation的基本动画, 使用起来也非常容易:

[UIView animateWithDuration:1.0f animations:^{

self.myView.center = location;

} completion:^(BOOL finished) {

NSLog(@"%@",NSStringFromCGRect(self.myView.frame));

}];

但是,只是封装了一些基本动画,  如果我们要实现比较复杂的动画(CAAnimationGroup),还是需要实现上面一坨代码。

缩放动画示例:

- (void)scaleAnim{

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

anim.toValue = @0.5;

anim.duration = 0.5;

anim.autoreverses = YES;  //自动翻转

[self.myView.layer addAnimation:anim forKey:nil];

}

旋转动画:

- (void)rotationAnim{

self.myView.layer.anchorPoint = CGPointMake(0.8, 0.8);

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

//不停地旋转

anim.toValue = @(2 * M_PI);

anim.repeatCount = HUGE_VALF;

anim.duration = 0.5;

//对于循环播放的动画效果,一定要removedOnCompletion设置为 No

anim.removedOnCompletion = NO;

[self.myView.layer  addAnimation:anim forKey:@"rotationAnim"];

}

暂停动画:

- (void)pauseAnim{

//1. 取出当前的动画时间,要暂停的时间  CoreAnimation absolute time

CFTimeInterval currentTime = [self.myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];

//2. 将动画的运行速度设置 == 0    ==》动画默认的运行速度是 1.0 /速度的比例

self.myView.layer.timeOffset = currentTime;

//3. 设置动画的时间偏移量    =》 让动画定格在该时间点

self.myView.layer.speed = 0.0f;

}

恢复动画:

- (void)continueAnim{

//1. 将动画的时间偏移量作为暂停时的时间点

CFTimeInterval pauseTime = self.myView.layer.timeOffset;

//2. 根据媒体时间计算出准确的启动动画时间  ,  对之前的暂停动画时间进行修正

CFTimeInterval beginTime = CACurrentMediaTime() - pauseTime;

//3. 设置图层的开始动画时间

self.myView.layer.beginTime = beginTime;

//4. 将timeOffset清空

self.myView.layer.timeOffset = 0.0f;

self.myView.layer.speed = 1.0f;

}

在appdelegate中获取controller的方法:

ViewController *viewController =  (ViewController *)[application.windows.firstObject rootViewController];

上一篇下一篇

猜你喜欢

热点阅读