Android - Animation 三角函数之美

概述

初中数学中的三角函数sin,cos…是超越函数一类函数,属于初等函数,通常用平面直角坐标系来定义三角函数,如下图。
sin(x)
在中学中我们通常把sin(x)的x赋值为角度,比如sin(30°)=1/2,而在计算机语言中x通常是弧度,sin(π/6)=1/2。
完整的正弦函数是这样的 y = a * sin(wx + b) + h : a影响振幅,w影响周期,h影响y位置,b为初相。

三角函数在GUI中的运用

Flyme 流量管理
Flyme 音乐频谱

Android 波浪控件原理

如上图流量管理中的水流效果,音乐频谱的波浪效果都是使用三角函数来实现:

流量管理 在屏幕上绘制出sin(2π)曲线,然后通过移动x位置即可,类似卷轴游戏一样循环移动即可。
音乐频谱 其实和流量管理是一样的,分别代表高中低频的三条波浪,通过动态改变的a的值来改变振幅,根据频率强弱变换移动速度。

Android 波浪控件实现

计算坐标点

1
2
3
4
5
6
7
...
// y = a * sin(2π) + b
for (int i = 0; i < mViewWidth; i++) {
// i/w, 把sin(2π)拉升到整个View宽度
mPointY[i] = (float) (30 * Math.sin(2 * Math.PI * i / mViewWidth));
}
...

绘制曲线

1
2
3
4
5
...
for (int i = 0; i < mViewWidth; i++) {
canvas.drawLine(i, mViewWidth - mDynamicPointY[i] - 400, i, mViewHeight, mPaint);
}
...

卷轴移动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
mXOffset += X_SPEED;
if (mXOffset > mViewWidth) {
mXOffset = 0;
}
...
...
// 超出屏幕的挪到前面
int yInterval = mPointY.length - mXOffset;
System.arraycopy(mPointY, 0, mDynamicPointY, mXOffset, yInterval);
System.arraycopy(mPointY, yInterval, mDynamicPointY, 0, mXOffset);
...

性能优化

优化刷新率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
long startTime = System.currentTimeMillis();
...
long endTime = System.currentTimeMillis();
int delay = 0;
if ((endTime - startTime) < 30) {
delay = (int) (30 - (endTime - startTime));
}
postInvalidateDelayed(delay);
}

BeautifulOfSin
完整代码:https://github.com/gavinliu/BeautifulOfSin

三角函数在动画中的运用

插值器算法

sin(x)随着角度的增大(或减小)而增大(或减小)
cos(x)随着角度的增大(或减小)而减小(或增大)
sin,cos也是围绕y轴不断循环的

所以可以很方便的用来算加速减速,循环,下面举个Android Property Animation中的TimeInterploator例子

android.view.animation.AccelerateDecelerateInterpolator
1
2
3
4
5
...
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
...
android.view.animation.CycleInterpolator
1
2
3
4
5
...
public float getInterpolation(float input) {
return (float)(Math.sin(2 * mCycles * Math.PI * input));
}
...

三角函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
sin(a+b)=sinacosb+cosasinb
sin(a-b)=sinacosb-sinbcosa
cos(a+b)=cosacosb-sinasinb
cos(a-b)=cosacosb+sinasinb
tan(a+b)=(tana+tanb)/(1-tanatanb)
tan(a-b)=(tana-tanb)/(1+tanatanb)
cot(a+b)=(cotacotb-1)/(cotb+cota)
cot(a-b)=(cotacotb+1)/(cotb-cota)
倍角公式
tan2a=2tana/[1-(tana)^2]
cos2a=(cosa)^2-(sina)^2=2(cosa)^2 -1=1-2(sina)^2
sin2a=2sina*cosa
半角公式
sin(a/2)=√((1-cosa)/2) sin(a/2)=-√((1-cosa)/2)
cos(a/2)=√((1+cosa)/2) cos(a/2)=-√((1+cosa)/2)
tan(a/2)=√((1-cosa)/((1+cosa)) tan(a/2)=-√((1-cosa)/((1+cosa))
cot(a/2)=√((1+cosa)/((1-cosa)) cot(a/2)=-√((1+cosa)/((1-cosa))
tan(a/2)=(1-cosa)/sina=sina/(1+cosa)
和差化积
2sinacosb=sin(a+b)+sin(a-b)
2cosasinb=sin(a+b)-sin(a-b) )
2cosacosb=cos(a+b)-sin(a-b)
-2sinasinb=cos(a+b)-cos(a-b)
sina+sinb=2sin((a+b)/2)cos((a-b)/2
cosa+cosb=2cos((a+b)/2)sin((a-b)/2)
tana+tanb=sin(a+b)/cosacosb
积化和差公式
sin(a)sin(b)=-1/2*[cos(a+b)-cos(a-b)]
cos(a)cos(b)=1/2*[cos(a+b)+cos(a-b)]
sin(a)cos(b)=1/2*[sin(a+b)+sin(a-b)]
诱导公式
sin(-a)=-sin(a)
cos(-a)=cos(a)
sin(pi/2-a)=cos(a)
cos(pi/2-a)=sin(a)
sin(pi/2+a)=cos(a)
cos(pi/2+a)=-sin(a)
sin(pi-a)=sin(a)
cos(pi-a)=-cos(a)
sin(pi+a)=-sin(a)
cos(pi+a)=-cos(a)
tga=tana=sina/cosa
万能公式
sin(a)= (2tan(a/2))/(1+tan^2(a/2))
cos(a)= (1-tan^2(a/2))/(1+tan^2(a/2))
tan(a)= (2tan(a/2))/(1-tan^2(a/2))
其它公式
a*sin(a)+b*cos(a)=sqrt(a^2+b^2)sin(a+c) [其中,tan(c)=b/a]
a*sin(a)-b*cos(a)=sqrt(a^2+b^2)cos(a-c) [其中,tan(c)=a/b]
1+sin(a)=(sin(a/2)+cos(a/2))^2
1-sin(a)=(sin(a/2)-cos(a/2))^2
其他非重点三角函数
csc(a)=1/sin(a)
sec(a)=1/cos(a)
双曲函数
sinh(a)=(e^a-e^(-a))/2
cosh(a)=(e^a+e^(-a))/2
tgh(a)=sinh(a)/cosh(a)

结语

有没有觉得水波纹的效果的实现其实很简单呢,说明数学真的很重要,尤其是线性代数,遗忘得差不多了,回头好好补补课。

Gavin Liu wechat
欢迎您扫一扫上面的二维码,订阅我的微信公众号!