1、需求:用 canvas 在上面的曲线上面加几个箭头,指明方向
2、问题:这个曲线我是第一次见,搞半天还发现不是圆的弧,是一种很奇怪的弧形,于是我就上网查 quadraticCurveTo 方法,才知道这个二次贝塞尔曲线的秘密
3、定义:它的形状由三个点决定:P0(起始点) , P1(控制点), P2 (终点),起始点和终点顾名思义,而控制点则控制了这个弧形的扭曲方向和扭曲程度,该曲线的发明是为了方便大家在电脑上画各种圆滑的弧线
公式:
令P0(x1,y1),P2(x2,y2), P1(cx,cy)
那么就是弧线上的点满足的方程就是
x = Math.pow(1-t, 2) * x1 + 2 * t * (1-t) * cx + Math.pow(t, 2) * x2
y = Math.pow(1-t, 2) * y1 + 2 * t * (1-t) * cy + Math.pow(t, 2) * y2
4、画弧线的主要代码:
ctx.moveTo(x1, y1);
ctx.quadraticCurveTo(cx, cy, x2, y2);
5、加箭头:设我现在要加的箭头数量是 arrowNum,而且我要均匀地点缀到弧线上面去
var arrowNum = arrowNum + 1;
var share = 1 / arrowNum;
for(var i = 1; i <= arrowNum; i++){
t = i * share;
x = Math.pow(1-t, 2) * x1 + 2 * t * (1-t) * cx + Math.pow(t, 2) * x2;
y = Math.pow(1-t, 2) * y1 + 2 * t * (1-t) * cy + Math.pow(t, 2) * y2;
// 加箭头方法就不详写了,主要讲的就是这个曲线上面取点的问题
addArrow(x, y);
}
6、补充箭头方向说明
一开始没考虑到这个问题,在曲线上面加箭头的时候,各个箭头的方向是随着曲线位置的变化而变化的,此处涉及到求取曲线上面的点的斜率的问题
已知曲线 P0(x1,y1),P2(x2,y2), P1(cx,cy)三个点位值,以及 x,y 关于 t 的函数方程,斜率这样求:
k= dy/dx = (dy/dt) / (dx/dt) 此处涉及求导,高数上面有介绍,我这里直接写结果了
k = ((-2) * (1 - t) * x1 + 2 * (1 - t) * cx - 2 * t * cx + 2 * t * x2 ) / ((-2) * (1 - t) * y1 + 2 * (1 - t) * cy - 2 * t * cy + 2 * t * y2)
k 就是箭头所在直线上的斜率,就相当于 tan(a),注意这里求导的角度只是直线的角度,至于箭头指向直线的那一头就要自己做判断了,这个a求出来也并不是度数,而时用 Math.PI 表示的角度,这里可能会涉及到转换,不要直接当成是度数来用