如何实现Siri中的波纹动画
来源:互联网 发布:微信 积分 源码下载 编辑:程序博客网 时间:2024/05/29 08:21
苹果手机上的siri语音波纹动画很有意思,本文将带领大家研究如何实现生动画效果。
本文中代码是基于android的Java,其他平台上可以参考算法自行实现。本文假定读者会实现自定义View,不会的同学可以自行百度,文中将不会赘述。
绘制正弦波
Siri波纹的基本型是正弦波,所以首先我们要能够绘制一条正弦波。
一切以代码说话:
protected void onDraw(Canvas canvas) { super.onDraw(canvas); float period = 2.0f;// 区域内,正弦波的周期 // 将绘图原点移动到区域中心 int width = getWidth(); int height = getHeight(); float midWidth = width / 2.0f; float midHeight = height / 2.0f; canvas.translate(midWidth, midHeight); // 初始化画笔 Paint paint = new Paint(); paint.setStrokeWidth(1);// 画线宽度 paint.setStyle(Style.STROKE);//空心效果 paint.setAntiAlias(true);//抗锯齿 paint.setColor(Color.BLACK); // 初始化线条 Path sinPath = new Path(); sinPath.moveTo(-midWidth, 0); // 计算线条 for (float x = -midWidth; x < midWidth; x++) { double sine = Math.sin(2 * Math.PI * period * (x / width));//计算该点上的正弦值 float y = (float) (midHeight * sine);// 将正弦值限定到绘图区的高度上 sinPath.lineTo(x, y); } canvas.drawPath(sinPath, paint);//绘制线条 canvas.restore();}
简单起见,我把所有的有效代码都放到了View.onDraw方法里面了。
这里,关键代码是这两句
double sine = Math.sin(2 * Math.PI * period * (x / width));
float y = (float) (midHeight * sine);
结合上下文,这两句话计算了x轴上对应的y值,即:
其中,坐标原点是绘图区的中心;period是x坐标上的正弦周期数,这里是2。
下图是这段代码绘制出的线条效果(图片做了缩小处理,会有不连贯效果):
振幅的抛物线修正
Siri中,波纹中间和两边的波动振幅是不同的,明显是两边小,中间大。那么我们可以定义一个函数,使得波纹振幅按照该函数变化。这里我定义的是二次函数如下,当然也可以自行设计合适的函数比如半个周期的正弦波。
修改之后的关键代码如下,加粗的部分是新添加的内容:
double scaling = 1 - Math.pow(x / midWidth, 2);
double sine = Math.sin(2 * Math.PI * period * (x / width));
float y = (float) (midHeight * sine * scaling);
如此修正后的正弦波纹看起来就像siri中的样子了,为了更明显的表示scaling的作用,我将两条抛物线画在了上面。
附抛物线代码:
Path parabola1 = new Path();parabola1.moveTo(-midWidth, 0);Path parabola2 = new Path();parabola2.moveTo(-midWidth, 0);// 计算线条for (float x = -midWidth; x < midWidth; x++) { double scaling = 1 - Math.pow(x / midWidth, 2); double sine = Math.sin(2 * Math.PI * period * (x / width));//计算该点上的正弦值 float y = (float) (midHeight * sine * scaling);// 将正弦值限定到绘图区的高度上 sinPath.lineTo(x, y); parabola1.lineTo(x, (float) scaling * midHeight); parabola2.lineTo(x, -(float) scaling * midHeight);}canvas.drawPath(sinPath, paint);//绘制正弦线canvas.drawPath(parabola1, paint);//绘制抛物线1canvas.drawPath(parabola2, paint);//绘制抛物线2
副波纹
Siri的波纹由多个线条组成的,下面我们就来添加几条副波纹。副波纹的条数和相关属性可以依个人爱好自行调整,这里我添加4条副波纹,包括主波纹一共是5条正弦波纹。
首先我们来定义一下几条波纹的宽度。在之前的绘图中,定义的画笔宽度一直是一个像素,这里我们给他改一下。
这里我定义了每条波纹的宽度,并依据屏幕像素密度进行修改,以减小不同设备上的视觉区别
float[] waveWidth = {3, 2, 2, 1, 1};DisplayMetrics metric = getResources().getDisplayMetrics();float density = metric.density; // 屏幕密度for (int i = 0; i < waveWidth.length; i++) { waveWidth[i] = waveWidth[i] * density / 2;}
接下来定义一下波纹的透明度,透明度可以使波纹看起来有层次感^_^。
float[] waveAlpha = {1.0f, 0.9f, 0.7f, 0.4f, 0.2f};
接下来要修改副波纹的振幅,这样几条波纹才会区别开来
float[] waveAmplitude = {1.0f, 0.7f, 0.4f, 0.1f, -0.2f};
下面,我要把这些属性都应用到几条波纹上:
for (int i = 0; i < waveWidth.length; i++) { paint.setStrokeWidth(waveWidth[i]);//画笔宽度 paint.setAlpha((int) (waveAlpha[i] * 255));//画笔透明度 sinPath.reset();//重置线条 sinPath.moveTo(-midWidth, 0); // 计算线条 for (float x = -midWidth; x < midWidth; x++) { double scaling = 1 - Math.pow(1 / midWidth * x, 2); double sine = Math.sin(2 * Math.PI * period * (x / width));//计算该点上的正弦值 float y = (float) (midHeight// 将正弦值限定到绘图区的高度上 * sine // 正弦值 * scaling// 振幅修正 - 距离中心越远,振幅越小 * waveAmplitude[i]// 副波纹振幅修正 ); sinPath.lineTo(x, y); } canvas.drawPath(sinPath, paint);//绘制线条}
这段代码的绘制效果如图:
现在有点样子了,不过几条波纹在
int[] wavePhase = {0, 6, -9, 15, -21};
…
double sine = Math.sin(2 * Math.PI * period * ((x + wavePhase[i]) / width));//计算该点上的正弦值
现在的效果就成这个样子了:
波纹移动
接下来就是让波纹移动了。很简单,在绘制正弦波纹的时候添加一个x轴上的偏移即可。
比如我们可以定义这样一个方法让波纹右移
private float phase;public void nextPhase(float n) { phase -= n; invalidate();}
然后在绘图时,将
double sine = Math.sin(2 * Math.PI * period * ((x + phase + wavePhase[i]) / width));//计算该点上的正弦值
做成动画的效果就是这样的:
按照音量调整振幅
Siri语音动画效果是依据环境音量调整振幅的,不过对此本文就不多做介绍了,感兴趣的同学可以去研究一下源码: Siri动画完整源码文件(Android版)
- 如何实现Siri中的波纹动画
- 波纹动画
- RecyclerView 实现item点击水波纹动画
- 如何在Windows phone8 中实现iphone中的siri,实现语音合成与语音识别
- iOS开发之iOS中的动画实现,通过CAShapeLayer、CAShapeLayer,CAReplicatorLayer实现炫酷的动画、雷达效果,波纹效果,咻一咻效果。iOS核心动画实现。
- Android代码实现长按显示波纹外扩动画
- 波纹外扩动画
- 波纹动画的研究
- 开机动画,水滴波纹
- iOS波纹动画
- 自定义波纹动画
- item点击波纹动画
- iOS波纹动画
- android如何实现按钮的点击水波纹效果:
- 带波纹动画的Layout
- iOS 动画 - 波纹 声波 水波
- 反编译 apk 以学习研究相关实现——Fuubo 波纹动画实现
- android实现波纹效果
- 50道编程题(有精力的同学看看)
- UIP协议栈二
- Java设计模式-目录
- [leetcode] Binary Tree Paths
- HDU 5401 Persistent Link/cut Tree
- 如何实现Siri中的波纹动画
- 利用Linux LiveCD迁移Windows到SSD硬盘
- 华为OJ平台试题 ——字符串:打印字符串中重复的字符
- 文章标题
- RT-Thread finsh源码分析: finsh_heap.h
- 2015 7 3 java核心技术卷一 7-10章 图形,事件处理,Swing组件和应用程序部署
- Linux下Sublime安装
- spmio内网源部署
- 【GDOI 2013模拟】总结