Javascript 使用画布绘制对角线曲线

Javascript 使用画布绘制对角线曲线,javascript,html,canvas,Javascript,Html,Canvas,我有一个使用画布的要求,我需要绘制一条曲线,使用quadraticCurveTo 我理解这是如何工作的,但我的问题是,我有一条对角线,我想指定“控制点”垂直于这条对角线,并与之保持一定距离(px)。例如: var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.moveTo(0, 0); ctx.quadraticCurveTo(?W, ?H, 100, 100); ctx.s

我有一个使用画布的要求,我需要绘制一条曲线,使用quadraticCurveTo

我理解这是如何工作的,但我的问题是,我有一条对角线,我想指定“控制点”垂直于这条对角线,并与之保持一定距离(px)。例如:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.moveTo(0, 0);
ctx.quadraticCurveTo(?W, ?H, 100, 100);
ctx.stroke();
我希望控制点(?W,?H)是,从“虚线”(0,0)到(100100)的50px,并且垂直于该虚线的中心点

我希望这是有道理的。为了进一步解释,使用直线很容易,因为:

ctx.moveTo(0, 0);
ctx.quadraticCurveTo(?W, ?H, 100, 0);
ctx.stroke();
所以W是50,H是50px(或者我希望它与虚线(0,0)到(0,100)的任何距离)

用一个简单的斜率,比如在我的例子中,它可能是可以计算出来的,但是对角线的斜率可以是任何东西,取决于起始点和结束点。起始点和结束点是从用户输入计算出来的,所以控制点需要从中动态计算自己

我花了几个月的时间在这上面,以我对画布的了解,我在哪里都找不到

非常感谢您的帮助

提前感谢

迈克

这里有一种方法-

步骤1:计算起点和终点之间的差值 只需从终点减去起点。我们将在接下来的步骤中重复使用这些值:

var diffX = x2 - x1,
    diffY = y2 - y1;
步骤2:找到两点之间的角度 我们使用
atan2()
函数重复使用diff来查找角度:

var angle = Math.atan2(diffY, diffX);
步骤3:找到直线的中点 使用线性插值,我们再次使用代表中心点的标准化值重复使用微分:

var mx = x1 + diffX * 0.5,
    my = y1 + diffY * 0.5;
步骤4:生成控制点 最后,将所有内容放在一起,使用中点,半径为相切角(这里的半径是从中点开始的长度,以像素为单位)

这里,我们将x/y的cos/sin顺序颠倒,并将cos取反,以使用角度的正切,而不是实际角度本身:

var cx = mx + radius * Math.sin(angle),
    cy = my - radius * Math.cos(angle);
现在我们可以将值传递给方法:

ctx.moveTo(x1, y1);
ctx.quadraticCurveTo(cx, cy, x2, y2);
你可以对半径求反,得到曲线的另一个方向,或者在最后的计算中,对cos/sin切换+/-,这实际上是个人喜好的问题

演示
var ctx=document.querySelector(“canvas”).getContext(“2d”);
变量x1=10,y1=10,x2=250,y2=250,半径=150;
//步骤1:计算起点和终点之间的差值
var diffX=x2-x1,
diffY=y2-y1;
//步骤2:找到两点之间的角度
变量角度=数学atan2(diffY,diffX);
//第三步:找到线的中心
var mx=x1+diffX*0.5,
my=y1+diffY*0.5;
//第四步:生产控制点
var cx=mx+半径*数学正弦(角度),
cy=我的半径*数学cos(角度);
//即:
ctx.fillStyle=ctx.strokeStyle=“#d00”;
ctx.fillRect(cx-2,cy-2,4,4);
ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);
ctx.moveTo(mx,my);ctx.lineTo(cx,cy);
ctx.stroke();ctx.beginPath();
//结果:
ctx.strokeStyle=“#000”;
ctx.lineWidth=3;
ctx.moveTo(x1,y1);
ctx.二次曲线(cx,cy,x2,y2);
ctx.stroke();

更新:将步骤简化到完美的程度!非常感谢。我真的需要复习一下数学。函数。你不会相信我花了多少时间在这上面,然后我很快就得到了答案!非常感谢!