【转载请注明出处】
作者:DrkCore (http://blog.youkuaiyun.com/DrkCore)
原文链接:(http://blog.youkuaiyun.com/drkcore/article/details/51822818)
这几天因为毕业之类的七七八八的事情有些日子没写博客了,刚好近日看到了 Bugly 发布的一篇关于自绘动画的博客《Android自绘动画实现与优化实战——以Tencent OS录音机波形动画为实例》,写的非常有深度但可惜没有放出源码,惊叹之余便有了亲自造个轮子的想法。
这是Bugly博客中给出的效果图,可以看到是非常的酷炫:
图片无法引用,如果想要查看效果的话可以到bugly公众号去查看原贴。
废话不多说,先放出效果图给大家看一下:
可以看到除了四处飞舞的小球和颜色不太对以外,大致的效果还是差不多的。
接下来让我们看看如何实现这些效果的。
当然,如果你想直接看代码可以直接看末尾。
图形函数
按照Bugly的博文中给出的公式我们首先在 Desmos 图形计算器上计算出需要绘制的图形,如下:
我们可以看到一共有三条波形,红色和蓝色波是录音波形的上下轮廓,绿色的波形则在中间,其振幅是上下两条波形的五分之一。
虽然有三条波形但其实我们只需要一个函数,其他两条都可以通过对该函数进行简单的数学换算得到:
用JAVA来表达也就是:
/**
* 计算波形函数中x对应的y值
*
* @param mapX x值
* @param offset 偏移量
* @return
*/
private double calcValue(float mapX, float offset) {
double sinFunc = Math.sin(0.75 * Math.PI * mapX - offset * Math.PI);//这里的offset * Math.PI是偏移量φ
double recessionFunc = Math.pow(4 / (4 + Math.pow(mapX, 4)), 2.5);
return 0.5 * sinFunc * recessionFunc;
}
正弦函数的公式是y=Asin(ωx+φ)+k,其中φ是偏移量,代码中通过 offset * Math.PI 来实现。这样我们只要在绘图的过程中将时间的流逝换算成偏移量即可实现波形的变换,配合Thread.sleep就可以倒腾出动画的效果。
图片中使用红色框图圈出的范围是我们关注的波形所在,取值如下:
x = [-2,2]
y = [-0.5,0.5]
显然所有的手机屏幕的尺寸都比这个范围大,因而我们需要将屏幕上的坐标点一一映射到这个区域之中,同时按照Bugly博客原文给出的思路我们只需要采样部分的点即可,映射的代码如下:
//采样点的数量,越高越精细,
//但高于一定限度后人眼察觉不出。
static final int SAMPLING_SIZE =