背景:前两天面试,问到项目中的动画效果实现,然后追问到怎么中途停止动画。
分析:这个问题我首先想到的就是CoreAnimation.中文翻译为核心动画。07年乔帮主在发布会上演示了它的强大也着重强调了它的easy。也就是告诉大家,要做动画就用我的这个核心动画处理。它的优点:
- 直接作用于CALayer上,而不是UIView上面的。
- 执行动画过程都是在后台操作,不会阻塞主线程。
我想在这两点优点面前,我不会选择其他的动画效果去实现了。
具体介绍一下:其实在天朝,APP更注重实用性,而不是你有多炫。所以大部分的应用不会添加很多华而不实的动画效果,当然游戏应用个人就喜欢越炫的越好了。虽然用的机会不是很多,但是如果在每款软件中添加一小点独特的动画效果也是能给人一种耳目一新的感觉的。
- CAAnimation
- CAAnimation所有动画类有几个?
- 这个问题是有次吃饭的时候朋友问到的,让我拼出来。我回家之后有做了一个总结,具体是以下四种:
- 我觉得最基础的就是CABasicAnimation(毕竟英文就是'basic'嘛),可以创建动画,对需要改变的控件图层进行改变。重点就是改变图层。最基本的平移,缩放、旋转处理都可以利用这个基本动画来达到效果了。
// 创建动画
CABasicAnimation *animat = [CABasicAnimation animation];
// 动画改变属性
animat.keyPath = @"position";
// 改变后的属性
animat.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
// 动画组件不被移除
animat.removedOnCompletion = NO;
// 保存最新状态
animat.fillMode = kCAFillModeForwards;
- CAKeyframeAnimation:关键帧动画。就是一帧一帧的动画了,一般用来处理GIF图片的。
// 图标抖动
// 定义帧动画
CAKeyframeAnimation *animat = [CAKeyframeAnimation animation];
// 改变弧度
animat.values = @[angleRadio(-5),angleRadio(5),angleRadio(-5)];
// 关键帧是什么必须有。
animat.keyPath = @"transform.rotation";
// 重复次数
animat.repeatCount = MAXFLOAT;
// 添加动画
[_imageView.layer addAnimation:animat forKey:nil];
-
关键帧keyPath是必须有的,其中的属性可以有很多种。可以对:
rotation
scale
translation
进行处理。 -
CAPropertyAnimation
- CAPropertyAnimation是CAAnimation的子类,但是不能直接使用,能直接使用的就是以上的两个子类。它有一个keyPath属性。所以两个子类才能使用keyPath属性,对CALayer属性值进行修改,达到动画效果。
-
CAAnimationGroup:很明显是一个动画组,也就是将单个的动画放到这个动画组里,形成多个动画的组合。其中的
animations
,用于保存一组动画对象。 -
CATransition转场动画
- 用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。
- 转场动画属性:
-
type:动画过渡类型
- subtype:动画过渡方向
- startProgress:动画起点位置(百分比)
- endProgress:动画终点
- 用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。
// 获取图片名称
NSString *imageName = [NSString stringWithFormat:@"%d",_i];
// 添加图片
self.imageView.image = [UIImage imageNamed:imageName];
_i++;
// 添加转场效果
CATransition *anim = [CATransition animation];
// 转场类型
anim.type = @"fade";
[self.imageView.layer addAnimation:anim forKey:nil];
- 介绍完了几个动画类,再回到问题怎么中途停止动画。我一开始想得应该有代理方法。一查之下,我找到了两个。
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
- 但是很遗憾,根据注释来看,这两个代理一个在动画开始的时候触发,一个在动画结束或者动画被移除时才触发。那么就只能手动去实现了。
- 既然是图层的变化,那么开始与结束也就应该是作用于图层了。
- 这里就提供了一个暂停动画和重新恢复动画的图层分类方法。
- (void)pauseAnimate
{
// 获取停止时间
CFTimeInterval pausedTime = [self convertTime:CACurrentMediaTime() fromLayer:nil];
self.speed = 0.0;
self.timeOffset = pausedTime;
}
- (void)resumeAnimate
{
// 获取暂停时间
CFTimeInterval pausedTime = [self timeOffset];
if (pausedTime > 0) {
self.speed = 1.0;
self.timeOffset = 0.0;
self.beginTime = 0.0;
CFTimeInterval timeSincePause = [self convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
// 设置开始时间
self.beginTime = timeSincePause;
}
}
网友评论