一款Loading动画的实现思路(四·完结篇)

感谢大家对前几篇的支持,这一篇,我们一鼓作气,把整个动画完成。

惯例,为了方便第一次来的同学,我先贴一下动画完成的效果图:


实现阶段4时,我们用了一种处理问题的方式,大约是这样的:

描述问题,直到足够清晰
把问题分解成一组小问题
利用经验处理可以解决的问题
经验无法解决的问题,我们去调研,调研结果会成为我们下次的经验

阶段5中,我们再应用一下这个方式(有疑惑的同学可以戳第三篇)。

先来看一下阶段5的效果图,
惯例,前几个阶段的动画我们用灰色快速表示,当前阶段使用彩色慢速表示,如图:

阶段5

看上去比阶段4还要复杂,别急,我们来描述一下:

一开始圆是扁的,圆里面有一条粗线,粗线的顶部和圆的顶部连在一起,
渐渐恢复原状,同时粗线渐渐变长,连到了圆的底部,与此同时,粗线的某处出现了两条线,分别向左下、右下延伸,渐渐连到了圆上。

很粗糙,但基本上描述出了这个阶段。

上文中我加黑了部分文字,这些文字很有标志性(有的平台转载时看不到加黑,可以戳原文查看)

“一开始”,指示出了本阶段动画的初始阶段
“渐渐”,指示出了动画
“同时”、“分别”,指示出了本阶段中可以拆分出的子动画

由此我们可以得到下面的描述:

初始:
圆:扁的
粗线:顶部和圆顶部连着,底部不连着
左下线:看不到
右下线:看不到

动画:
圆:恢复到正常的形状
粗线:变长
左下线:出现并变长
右下线:出现并变长

结束:
圆:正常的形状
粗线:顶点、底点分别与圆的顶点、底点连着
左下线:起点在粗线上,终点在圆上
右下线:起点在粗线上,终点在圆上

和前面的描述相比,这个描述形式化了,虽然还比较粗略,但已经清晰的标明动画被拆分成了4部分,各部分的初始及结束状态也有了。

我们给4部分染上不同的颜色看一下:

阶段5 多彩版

是不是比之前的清晰多了,
描述问题分解问题,到这里我们就完成了。

接下来就是思考动画的方案了:

圆:阶段4中是执行transform.scale.y动画变扁了,本阶段将transform恢复为CATransform3DIdentity就可以了;
粗线:阶段4中是从无成长到一定长度,用的stroke方案(想了解stroke方案的同学请戳第二篇),这个阶段就是继续变长,沿用stroke方案就可以了;
左下线、右下线:本质是一样,从无成长到一定长度,类比粗线可知,可以使用stroke方案;

这些方案都是以前的经验,阶段5可以不用调研了。

接下来就是找关键的节点值了:

对于一个动画来讲,关键的节点就是初始状态和结束状态,前几篇中我们一起找过了关键的节点值,相信大家已经有感觉了,本文我们就不再找了。

我们一起来看一下阶段5中特殊的地方:

前文中说到粗线时,我说的是继续变长
继续听上去就有延续的意思,看上去,粗线两个阶段的动画可以合并成一个。

回忆一下,阶段4中粗线的path起点是圆未变形时的顶点,终点是圆未变形时的圆心,strokeEnd是从path起点逐渐stroke到path的终点,如下图(灰色是path,蓝色是stroke,SS、SE是初始,SS'、SE'是结束):


阶段4 粗线

结合阶段5,我们可以将path的终点修改为圆的底点,这样一来,就将阶段4的strokeEnd修改为从path的起点stroke到path的1/2处,如下图:


新阶段4 粗线

而阶段5的strokeEnd就是在阶段4的基础上继续stroke到path的终点,这样两个阶段的动画就合到一起了,如下图:


阶段5 粗线

有的同学可能会说,早知道是这样,一开始就这样写就可以了。

这么说的是有道理的,有的人习惯这样,先分阶段考虑,再整体看一下各阶段,该合并的合并,该修改的修改,方案成形,最后写代码,这是个很好的方式。

然而对我来说,阶段性的成就感很重要,每当我看到一个阶段的动画在我眼前动起来,感觉都很爽,所以我还是习惯于逐个阶段的实现,有需要时重构前面的阶段,只要逻辑清晰,重构起来问题不大。

每个人都能找到最适合自己的方式,这本身就是一种乐趣。

好了,阶段5我们聊了很多,后面的阶段我们就简要的说一下了。
从完整的效果图可知,这个动画是有成功和失败两个状态的,因此我们分开来看。

成功状态,从阶段5到阶段6_success:


阶段6_success

描述一下:
圆变色
对号渐渐出现(stroke)

失败状态,先是从阶段3直接到阶段6_fail:


阶段6_fail

描述一下:
圆变色
叹号的上半部分渐渐出现(stroke)
叹号的下半部分渐渐出现(stroke)

然后从阶段6_fail到阶段7_fail:


阶段7_fail

描述一下:
叹号绕圆心左右晃几下(rotate)

阶段7_fail要简单的说一下:

在阶段6_fail中,叹号被拆分成了上下两个layer,而在阶段7_fail中两者又是作为一个整体动的,我们要让它们分别执行动画么?

不是的,一个独立的动画应该只涉及一个对象,两个layer有共同的superLayer,让superLayer执行动画就可以了,假如superLayer还有其他subLayer,不方便执行动画,我们在两个layer和superLayer中间插入一层专门执行动画的layer就可以了。

到这里,我们的动画就完成了,完整代码请移步GitHub上的OneLoadingAnimation工程

在结束之前,我们简单说一下阶段1另一种思路(想看看阶段1的同学请戳第一篇),这个思路更符合直觉,这个思路是受简友YouXianMing第一篇中的评论启发,感谢。

先回忆一下阶段1的样子:


阶段1

描述一下:
圆从不完整渐渐变到完整(stroke)
圆在渐渐旋转(rotate)

由此我们得出,一个圆同时执行stroke和rotate动画就可以了,下面是示意代码

// 不完整的示意代码
- (void)doStep1 {
    // 不用自定义layer了
    self.arcToCircleLayer = [CAShapeLayer layer]; 

    // stroke动画
    CABasicAnimation *ssAnima = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    CABasicAnimation *seAnima = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];

    // rotate动画
    CABasicAnimation *rotateAnima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

    // 同时执行
    CAAnimationGroup *animation = [CAAnimationGroup animation];
    animation.animations = @[ssAnima, seAnima, rotateAnima];
}

是不是比第一篇的实现方式更清晰,
我们也可以看到,问题分解后,局部的优化也比较方便,
这部分的完整代码我放到了工程的OneLoadingAnimationStep1Another目录下。

有的同学还记得,我们这是一个简化的版本,阶段4中原动效中圆的不规则变形被我处理成了规则变形,
为了思路不被卡住,我选择了暂时简化,完成之后,我们可以再去优化

为了弥补这个缺憾,我会开一个外篇,专门聊一下圆不规则变形的实现,欢迎大家到时来捧场;

另,有简友在简信中提到了Swift,因此我写了一个Swift版的实现,放在了工程的OneLoadingAnimationCompleteSwift目录下,由于我的Swift水平不够,代码里还有坑,仅供参考。

本系列的主线到这就完结了,非常感谢大家的捧场!

完整代码

请参考GitHub上OneLoadingAnimation工程

本系列的�传送门

鸣谢及推荐

相关链接

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

推荐阅读更多精彩内容

  • �感谢大家对前两篇的支持,在第一篇的评论中,简友YouXianMing提出了更好的实现思路,同样在评论中,原动效设...
    柯烂阅读 5,517评论 22 73
  • 18- UIBezierPath官方API中文翻译(待校对) ----------------- 华丽的分割线 -...
    醉卧栏杆听雨声阅读 965评论 1 1
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 清明 清明时节雨飘飘,祭祖焚香烟袅袅。 生前当须孝心尽,事后不必把纸烧。 人去物空方思起,已让桃花笑弯腰。 纵烧金...
    生达成长规划阅读 293评论 0 1
  • 端午放了三天假,我压根就没出过门,整天窝宿舍腐烂发臭,因为我的人生格言就是我偶像咪蒙的人生格言,生命在于一动不动。...
    好萌66阅读 214评论 0 0