canvas中的三角函数

在回忆三角函数前,先复习下弧度和角度之间的关系。

我们把长度等于半径长的弧所对应的圆心角叫做一弧度的角,读作弧度,用rad表示。

角度和弧度之间的换算:

1
2
3
4
5
6
360 = 2π rad
180 = π rad
// 将x角度转换为弧度
rad = x * 2 * π / 360
// 将x弧度抓换为角度
rangle = rad * 360 / 2 * π

JavaScript的内置对象Math提供一系列数学的常数和数学方法。所有的属性和方法都必须在Math对象上调用。

其中三角函数相关的为

  • 常数π,Math.PI
  • 三角函数,sin, cos, tan(参数为弧度)
  • 反三角函数:acos, asin, atan, atan2(返回值为弧度)

三角函数

在js的二维环境中,夹角表示向量和x轴的夹角,同时,角度从正向x轴开始,顺时针旋转。这个和以前数据中学习的三角函数正好相反。

  • 数学中坐标轴y轴向上为加,夹角为逆时针旋转
  • js二维环境中,y轴向下为加,夹角为顺时针旋转

正弦 sin表示对比斜:sin(θ) = y / r
余弦 cos表示临比斜:cos(θ) = x / y
正切 tan表示对比临:tan(θ) = y / x
余切 cot表示临比对:cot(θ) = x / y
Alt text
各曲线对应的图(x轴为角度,y轴为对应的值)
Alt text
复习了上述知识,我们可以来操作实例。

实例

Question:知道一个角度θ,画出这个方向的线段。

为了更显而易见,我们用canvas画图来表示。canvas的载体:

1
2
<h3>不同角度点的线段</h3>
<canvas id="canvas-sin-test" width="240" height="240"></canvas>

js获取canvas的2d环境:

1
2
var canvas = document.getElementById('canvas-sin-test');
var context = canvas.getContext('2d');

为了方便展示,我们定义原点为(100, 100),半径r为50,角度θ为30。

1
2
3
var origin = {x: 100, y: 100};
var radious = 50;
var rangle = 30;

画出直线需要两个点,一个为原点,我们需要再选取一个点。想象以原点为圆心,半径为r,顺时针旋转角度θ,获取角度为θ时的点。注意使用JavaScript的三角函数的时候需要将角度转换为弧度。

1
2
3
var radian = rangle * 2 * Math.PI / 360;
var x0 = Math.cos(radian) * radious + origin.x;
var y0 = Math.sin(radian) * radious + orgin.y;

这样我们就知道了这个点(x0, y0)。然后连接原点和这个点,就可以获得直线这个角度的直线了。

1
2
3
4
5
6
7
// 画出这个线
context.beginPath();
context.strokeStyle = 'yellow';
context.moveTo(origin.x, origin.y);
context.lineTo(x0, y0);
context.stroke();
context.closePath();

反三角函数

反正弦 asin(y / r) = θ
反余弦 acos(x / r) = θ
反正切 atan(x / y) = θ

反三角函数用来知道对应的边长,来求得角度。

比如,距离原点为80,知道x轴长度为40, 求之间的夹角以及这个直线。

我们来转化一下,也就是r为80, 原点到x0为40,我们需要知道夹角θ和y0。这时可以使用反余弦函数。

1
2
3
4
5
6
7
8
// 知道线段的长度,知道x
var radious = 80;
var xlen = 40;

var radian = Math.acos(xlen / radious);

var y0 = Math.sin(radian) * radious + origin.y;
var x0 = origin.x + xlen;

照样可以画出线段,我们发现,正好这个角度是60度。因为cos(60) = 1/2

更多的是知道原点和一个点的坐标(x, y),然后求这个夹角,这时候需要用到反正切atan。θ = Math.atan(y / x)

但是因为atan的周期性,一个数字的正切值不止一个(具体可以看上面的tan曲线图)。正切函数的周期是π,所以两个相差180度的角具有相同的值。

所以,程序中我们使用Math.atan2这个函数来求斜率的角度。

atan2(y, x)返回一个[-π, π]之间的角度,代表点(x, y)对应的偏离x轴的角度。

所以,只要知道了一个点和与原点,就可以用Math.atan2(y0 - originY, x0 - originX)知道斜率。

比如:有一个枪口可以发射出来子弹,鼠标决定着枪口的方向,如何计算的子弹的走向。

转换一下,枪口,好比原点(originX, originY),鼠标所在的地方好比一个已知点(x0, y0)。求得斜率:

1
2
3
4

var relativeX = x - ballOrgin.x;
var relativeY = y - ballOrgin.y;
var radian = Math.atan2(relativeY, relativeX);

然后根据斜率给一个初始速度的x轴分量和y轴分量:

1
2
3
// 40为初始速度
var xVelocity =40 * ( Math.cos(radian));
var yVelocity = 40 * (Math.sin(radian));


在学习canvas的游戏,涉及到的一些三角函数操作总是乱乱的,特别整理下,以后用起来可以娴熟一点。

码字辛苦,打赏个咖啡☕️可好?💘