一款Loading动画的实现思路(三)

�感谢大家对前两篇的支持,在第一篇的评论中,简友YouXianMing提出了更好的实现思路,同样在评论中,原动效设计者 moonjoin亲自现身捧场,非常感谢!�这也说明以分享来抛砖引玉是有效果的。

惯例,为了让第一次来的同学对本系列有所了解,我先贴一下�完整的效果图,有兴趣的同学,请移步本系列第一篇,可以的话请多提提建议,非常感谢,以下是效果图

不多说了,我们开始第三篇。

前两篇�聊到了一些技术,而这一篇我们则侧重于思路,一起来聊一下阶段3和阶段4。

那么,我们先看一下阶段3的效果图,惯例,前几个阶段的动画我们用灰色 正常速度表示,当前阶段则使用彩色慢速,如图


阶段3

有的同学要说了,这个太简单了,就是一平移嘛。

没错,就是平移。可能和我一样,很多同学最早接触的动画就是平移、旋转和缩放,�可以算基本功了。

所以阶段3,我们就不多聊了,方案有很多种,比如修改layer的position.y、transform.translation.y都可以(对此不熟悉的同学请戳官方文档中的可动画的属性动画支持的key path),甚至可以用本系列第二篇提到的stroke方案。

阶段3不是没有价值,因为从阶段3中我们可以得到一个重要结论,那就是:我们可以利用经验来解决问题

这�句看上去像是废话,不要急,我们接下来要看看,�把分解问题和这个结论结合起来,会是什么效果。

下面是阶段4的效果图,大家请看


阶段4

�是不是感觉比前3个阶段复杂,为什么会有这种感觉呢?

一个重要的原因是,我们觉察到阶段4是多个动画组合而成的,不像前3个阶段那样是单个动画。

�像我一样单核的同学估计要疯了,恩,这儿在变,�恩?那儿怎么也在变?
所以我们�最好还是把这组动画分解一下,一个一个来处理

但是怎么分解呢,�一时可能没思路,那我们不如来描述一下这个动画吧。
比如这样:“一个圆被头顶上的线砸扁了,线砸进圆�里,�线变粗了。”

但仔细看看,砸进去的过程中,线在圆外的部分是细的,在圆内的部分是粗的,有点复杂,�不如就以圆为界,分成一细一粗两条线吧。

我们再描述一次:“一个圆被头顶上的细线砸扁了,细线慢慢消失了,圆里面慢慢出现了一条粗线。”

这个描述里都有什么?
圆渐渐扁了,圆外的细线渐渐消失了,圆内的粗线渐渐出现了。
渐渐,就是动画的意思。

这样我们就分解出了3个简单的动画,
为了更直观,我们给圆、细线、粗线分别染上不同的颜色,请看下图

阶段4 多彩版

思路是不是已经出来了,圆变扁,大家应该想到了基本功里的缩放(transform.scale.y),线消失与线出现,有的同学可能想到了本系列第二篇提到的stroke方案(CAShapeLayer的strokeStart和strokeEnd)。

至此,我们已经通过描述问题把动画分解了,并且发现可以利用经验实现分解后的动画

接下来就是找重要节点的值了。

我们发现,3者的交界是圆的顶点,看来这是一个重要的节点。
在本示例中,我们假设动画结束时,圆的缩放系数scale为0.8,请看下图

图中红点就是圆的顶点,由可知,动画开始时,顶点y坐标就是center.y - r,结束时就是在这个基础加上缩放的部分2r * (1 - scale),即center + 2r * (1 - scale)处。

再看细线,细线的长度可以从阶段3中拿到,动画开始时有长度(下图中灰色线),动画结束时,SS、SE�重合,线就消失了(下图中蓝色圆的顶点),如图


细线

再看粗线,�我们假设结束时,粗线的底部位于圆未变形时的圆心处,动画开始时SS、SE重合,线看不到(下图中灰色圆的顶点),动画结束时,SS、SE分别到了不同位置,线就出现了(下图中蓝色线),如图


粗线

�还不是很清楚的同学,可以在纸上画一画,画着画着就明白了。
至此,关键节点的值都找到了。

下面我们来看一个问题。
有的同学注意到了,这个圆的缩放和我们�常用的不一样,�常用的是圆心不变,圆顶点和底点分别向圆心靠拢,形成椭圆的效果。而这个动画中,是圆底点不动,顶点和圆心都向底点靠拢。

有经验的同学可能要提到一个词了,anchor point ,这个我先截一张官方文档Core Animation Programming Guide中的示意图,图中用旋转transform示意了anchor point和position。

不严谨的说,transform时,anchor point就是不动的那个点,其它点基于anchor point进行�计算(具体大家还是要看一下Core Animation Programming Guide文档,或它的翻译版)。

具体到本例中,anchor point应该在圆的底点,这样缩放时,就是底点不动,其他点基于底点计算了。

理解了anchor point,有的同学写出了这一句。

self.arcToCircleLayer.anchorPoint = CGPointMake(0.5, 1);

这一句逻辑是对的,x等于0.5即anchor point在x轴上位于圆的中心,y�等于1即anchor point在y轴上位于圆的底点,和我们前文中的说到的要求一致。

但执行时,却会惊喜的发现,圆的位置发生了一次突变,如下图


这是怎么了,想一想,圆的大小与位置��可以认为是frame的体现,查看一下CALayer的文档,在frame的Discussion中,有这么一句

the frame rectangle is a computed property that is derived from the values in the bounds, anchorPoint and position properties.

也就是说frame是根据bounds、anchorPoint和position这3个属性算出来的,我们没有改变bounds和position,而单单改变了anchorPoint,frame自然也跟着变了。

怎么解决呢,答案依然在frame的Discussion中,如下

When you assign a new value to this property, the layer changes its position and bounds properties to match the rectangle you specified.

文中的this property就是frame,这段文字说明,我们给frame指定新值,layer会自动调整position和bounds。
那就简单了,我们设置anchor point后,再将圆的frame设置回之前的值,如下

CGRect frame = self.arcToCircleLayer.frame;
self.arcToCircleLayer.anchorPoint = CGPointMake(0.5, 1);
self.arcToCircleLayer.frame = frame;

篇幅关系,我就不贴大段代码了,完整代码大家可以查看GitHub上OneLoadingAnimation工程的OneLoadingAnimationStep4目录。

为方便大家查看,我贴了一点代码,说明一下代码的结构,如下

// 第4阶段
- (void)doStep4 {
    [self doStep4a];
    [self doStep4b];
    [self doStep4c];
}
// 4阶段a:小圆变形
- (void)doStep4a {}

// 4阶段b:逐渐消失的竖线
- (void)doStep4b {}

// 4阶段c:逐渐出现的竖线
- (void)doStep4c {}

用1、2、3来表示某阶段,用a、b、c来表示阶段内某个动画,这显然不是良好的命名,但在这个示例中,这样也许更清晰。

篇幅所限,我们在下一篇中再聊后续的阶段,大家有兴趣的话,可以分解一下后面的动画,�找一找感觉。

本文中提到解决问题的思路,�相当一部分得益于V.Anton Spraul的《像程序员一样思考》,ISBN号9787115383396,有兴趣的同学可以看一下,写的很好。

第三篇到这就告一段落了,非常感谢大家的观看,我们下一篇再会。

阶段4中我简化的部分

大家仔细查看原动效的话,会发现圆的变化是不规则的。
原设计更符合直觉,比如大家把球放到地上,拿一个手指去按它,手指按的部分和球与地面接触的部分,变形度肯定是不一样的。
为了实现简单,我将圆的变化处理成了规则的变化,即从圆渐渐变成了椭圆。
后续我会单独开一篇和大家聊一下圆不规则变化的实现,敬请期待。

完整代码

请参考GitHub上OneLoadingAnimation的OneLoadingAnimationStep3和OneLoadingAnimationStep4目录。

本系列的�传送门

鸣谢及推荐

相关链接

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

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,001评论 5 13
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,321评论 6 30
  • 111. [动画系统]如何将其他类型的动画转换成关键帧动画? 动画->点缓存->关键帧 112. [动画]Unit...
    胤醚貔貅阅读 12,571评论 3 90
  • 感谢大家对前几篇的支持,这一篇,我们一鼓作气,把整个动画完成。 惯例,为了方便第一次来的同学,我先贴一下动画完成的...
    柯烂阅读 5,307评论 18 74
  • 本文将分为四个部分介绍核心动画: 第一部分将介绍核心动画的基本概念。 第二部分将介绍动画实现原理。 第三部分将介绍...
    曲年阅读 3,134评论 1 9