备注:两个渐变色是可以围着矩形框一直旋转的(偷个懒,不搞gif图了)。
实现方案很多,具体可以是下面几种方式:
- 此篇的主题:path动画
- svg动画,svg图片也是基于path的,结合属性动画原理可以说和path动画一致。
- ondraw绘制,涉及的计算量太大,这个就不考虑了。
- 此篇重点描述path动画,svg动画稍候会有文章对齐解释。
结合到path动画又有两种实现方式,一种是公司同事实现,另一种是大神的PathAnimView,此篇文章着重解释学习后面一种,前面涉及到公司只是提供思路方法,不管怎样都非常感谢大家在我的学习道路上提供的帮助。
path动画核心要素:需要绘制的目的path在已固定的原路径path上绘制,动画路径无论多么复杂都是已固定写好的原路径,针对动态的目的路径只是原路径上的一截
方案一:
path路径示意图
- 效果涉及两个渐变条旋转,所以每个渐变色都对应着一个path,需要注意的是path的起点,每一个渐变色都是从标注的点开始绘制,所以两个对称的起点使得渐变色依次旋转。 按照示意图标注的path 结构依次画一个圆角矩形,并将其反复画n倍,让该path成为n个圆角矩形重叠path,为后面动画提供源path(绘制n倍是为了让其旋转的更为流畅,后续会简单解释)
- path动画除了path路径外,还需要发动机,其发动机就是属性动画,动画的本质就是在一段时间内执行一连串的动作并且让其连贯起来,需要注意的是此处属性动画并不是常用的ObjectAnimation而是其父类ValueAnimator。
- 源路径和发动机都有了,此处还得借助先前文章提到的path的测绘工具类,PathMeasure,该类绑定path后可以测量出path的length及其给定一个distance可以测绘出给定点的x,y坐标同时还可以指定start和stop后截取原始的一段路径。
- 结合上面及其path动画的核心要素此效果就很简单了,valueanimator提供一个0到1的动画,结合动画的每一个值和源路径path的length计算start,然后截取单个圆角矩形的一段加上start作为stop(就是计算渐变色的距离)通过pathmeasure计算所得目的路径后刷新view(在ondraw中会通过渐变色画笔绘制目的路径),动画的0,1对应着原路径的path的0到length,所以源路径越长旋转路径效果越好。
方案二
PathAnimview核心原理和上面基本一致,只是结合到具体的实现略有不同,下面以代码的方式分析其最基本的pathanim。 - PathAnimview是一个很不错的封装框架,除了简单的pathanim还封装了其他一些很复杂的view动画,即时简单的pathanim其可以外面view指定任何path源路径,也是很方便的实现方案了。
-
首先看其实现view ondraw的实现:
pathanimview代码很简单就是先将源path绘制到view上,再将animPath绘制到view上。源path是外面view使用时候指定,那么当前重点放到animPath上,由view的其他代码很方便检索到pathanim的生成是在工具类PathAnimHelper上,简单代码为了节省篇幅就不一一备注了。
-
PathAnimView提供了启动动画的api(startAnim),下面看一下startAnim的代码实现:
startAnim此段代码做了两件事一是测绘原始路径,而是将测绘路径后的参数数据交给loopAnim去执行动画,测绘原始路径需要注意的是,原始path可能并不是一条单独的线(path对线的数量判断是根据是否闭合),针对这种情况进行了多个测绘获取到最终的路径长度。
-
继续去看loopAnim的代码实现:
loopAnim代码也不复杂生成一个属性动画并启动动画,在onAnimationUpdate中去更新刷view,到此为止和方案一是没有什么区别的(核心原理一样)
PathAnimView支持动画重复播放,此逻辑是在repeat监听中实现。
生成目的路径的代码在回调方法onPathAnimCallback中实现,即: -
image.png
系统原生动画始终是以0为起点,动画控制的是终点,终点值是path的总路径和0到1区间值的乘积,截取该段路径作为动画路径在view上绘制,此动画原为图片的加载进度条实现,不过这个再结合属性动画的循环播放也可以实现上面的渐变色循环转圈的效果
- PathAnimView的动画的实现与效果还有些瑕疵,效果中是一段path旋转,而当前效果是animpath不断扩展,进而当动画到1的时候会完全覆盖原有path,这个修改很简单,animpath的start不固定在0,而是受属性动画控制,stop是固定一段即可。
结合上面的实现分析两者实现的区别及其path动画的要点:
- path动画核心实现大同小异,都是两段path并借助于属性动画
- 两者实现思想不同,方案一是属性动画作用一个很大很大的一个源path路径,且动画时间也很长基本是一个页面的停留时间大约3分钟内(有点擦边球的意味),后者不同,后者是处理单个path路径动画时间设置也很小大约几秒即可,他是依赖于不停的循环播放动画,即一个是很长的动画在一个重叠的路径上不停的旋转绘制,一个是动画时长很小而不停的循环播放
- 从性能和一些逻辑上后面方案更可取,效果上调试完成基本差不多。
- 再次重申:path动画核心要素是目的路径在原路径上执行行为,路径在复杂也是固定的源路径复杂,目的路径不过是原路径上的一小段而已。源路径的绘制还得借助先前的文章介绍去实现。
参考文章
path实现小球的轨迹动画
path实现波浪动画,轨迹动画
path实现圆的动画
Android自定义曲线路径动画框架
结合path和canvas实现心形轨迹动画
PathAnimView实现
github工程:pathAnimView的实现
path实现b站弹幕页面的背景效果
网友评论