iOS 关键帧动画

级别:★★☆☆☆
标签:「iOS CAKeyframeAnimation」「iOS 关键帧动画」「CAKeyframeAnimation values」「CAKeyframeAnimation path」
作者: Xs·H
审校: QiShare团队

最近的项目需求涉及到一些动画效果。对于基本的动画,可以使用QiShare之前分享过的CABasicAnimation实现,而和路径相关的动画(例如图1的折线动画)可以使用CAKeyframeAnimation实现。

图1 折线动画效果

CAKeyframeAnimation和CABasicAnimation都是CAPropertyAnimation的子类。CABasicAnimation可以控制动画的起点(fromValue)和终点(toValue),而CAKeyframeAnimation可以控制动画的全过程。所以,可以将CABasicAnimation理解成只关注起点和终点的CAKeyframeAnimation。

对比CABasicAnimation来说,CAKeyframeAnimation是通过控制动画的“关键帧”“步调”(关键帧执行的时间)来控制动画过程的。

一、CAKeyframeAnimation使用“values”或“path”属性来控制动画的关键帧

values:可选的NSArray对象,存放多个value,每个value就是一个keyframe(关键帧)。在动画过程中,关键帧会依序显示出来。
path:可选的CGPathRef对象,指定动画的路径,可让CALayer的anchorPointposition按照路径变化。除了“moveTo”之外,路径中的每个点都是一个关键帧。如果需要沿路径匀速动画,需要将calculationMode属性设置为paced。当pathnil时,values属性被覆盖。

二、CAKeyframeAnimation使用“keyTimes”属性来控制动画的步调

keyTimes: 可选的NSArray对象,存放多个keyTime,每个keyTime都是[0, 1]区间内的浮点数所对应的NSNumber,与values中的关键帧一一对应,控制关键帧发生的时间。
PS:当valuespath覆盖时,keyTimes作用于path。(path的优先级较高)

三、使用CAKeyframeAnimation实现图1的折线动画效果

为了辅助分析动画过程,我们为动画加上轨迹(后文只分析动画本身,不分析轨迹),如图2。

图2 带轨迹的折线动画效果
1) 像使用CABasicAnimation一样初始化CAKeyframeAnimation的对象
// 初始化动画
self.animation = [CAKeyframeAnimation animation];
self.animation.keyPath = @"position";
self.animation.delegate = self;
self.animation.duration = 5.0;
self.animation.repeatCount = 1.0;
self.animation.removedOnCompletion = NO;
self.animation.fillMode = kCAFillModeForwards;
self.animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
2) 使用“values”和“keyTimes”属性设置动画的关键帧和步调
// 设置动画的关键帧数组
self.animation.values = @[[NSValue valueWithCGPoint:self.imageView.center],// 不能省略起点(1, 1)
                          [NSValue valueWithCGPoint:(CGPoint){self.squareSide * 2, self.squareSide * 1}],// 右移1格
                          [NSValue valueWithCGPoint:(CGPoint){self.squareSide * 2, self.squareSide * 5}],// 下移4格
                          [NSValue valueWithCGPoint:(CGPoint){self.squareSide * 5, self.squareSide * 5}],// 右移3格
                          [NSValue valueWithCGPoint:(CGPoint){self.squareSide * 5, self.squareSide * 7}]// 下移2格
                          ];
// 设置动画的步调
self.animation.keyTimes = @[@.0, @.1, @.5, @.8, @1.0];
// self.animation.calculationMode = kCAAnimationPaced;// 可以替代上面的keyTimes实现匀速效果

PS: 上述代码中的keyTimes是根据values的值进行设定的,以达到动画匀速的效果。若不设置keyTimes,动画时长(duration)将被平均分配给4段动画。

3) 像使用CABasicAnimation一样为layer添加动画和移除动画
if (start) {
    [self.imageView.layer addAnimation:_animation forKey:@"animation"];// 执行动画
}
else {
    [self.imageView.layer removeAnimationForKey:@"animation"];// 移除动画
}

上面有介绍到,path属性同样可以设置动画的关键帧,并且当path不为nil时会覆盖values
所以,步骤2)可以替换为“path”“keyTimes”的方式。

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, self.imageView.center.x, self.imageView.center.y);
CGPathAddLineToPoint(path, NULL, self.squareSide * 2, self.squareSide * 1);// 右移1格
CGPathAddLineToPoint(path, NULL, self.squareSide * 2, self.squareSide * 5);// 下移4格
CGPathAddLineToPoint(path, NULL, self.squareSide * 5, self.squareSide * 5);// 右移3格
CGPathAddLineToPoint(path, NULL, self.squareSide * 5, self.squareSide * 7);// 下移2格
self.animation.keyTimes = @[@.0, @.1, @.5, @.8, @1.0];
// self.animation.calculationMode = kCAAnimationPaced;// 可以替代上面的keyTimes实现匀速效果
self.animation.path = path;
CGPathRelease(path);

四、使用CAKeyframeAnimation实现曲线动画

CAKeyframeAnimation的valuespath属性具有强大的功能,尤其是path,可以方便的制定自定义动画路径,比如图3的椭圆动画效果。

图3 椭圆动画效果

使用path制定上述椭圆路径的代码如下:

CGRect drawRect = (CGRect){self.squareSide, self.squareSide, self.squareSide * 8, self.squareSide * 6};
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, drawRect);
self.animation.keyTimes = @[@.0, @.25, @0.5, @0.75, @1.0];
// self.animation.calculationMode = kCAAnimationPaced;
self.animation.path = path;

示例源码可从GitHub的QiShare开源库中获取。


了解更多iOS及相关新技术,请关注我们的公众号:

关注我们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)

推荐文章:
iOS 绘制渐变·基础篇

iOS 绘制渐变·实例篇
iOS 编写高质量Objective-C代码(七)
奇舞周刊

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容