概述

初中数学中的三角函数 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
8
...
// 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)

结语

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