使用画布绘制对角线

时间:2015-04-10 09:46:47

标签: javascript html5 canvas

我需要使用画布,我需要使用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),比如说"虚线"是50px? (0,0)到(100,100)并垂直于该虚线的中心点。

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

ctx.moveTo(0, 0);
ctx.quadraticCurveTo(?W, ?H, 100, 0);
ctx.stroke();

所以?W将是50而?H将是50px(或者我希望它垂直于虚线(0,0)到(0,100)的任何距离。

使用简单的斜率,就像在我的例子中一样,它可能可以解决但是对角线的斜率可以是任何东西,取决于起点和终点。起点和终点是根据用户输入计算出来的,因此控制点需要从中动态计算自己。

我花了好几个月的时间,凭借我对画布的了解,我得到了无处可去的地方。

非常感谢任何帮助!

提前感谢!

麦克

1 个答案:

答案 0 :(得分:3)

这是一种方式 -

Snapshot

步骤1:计算起点和终点之间的差值

简单地从终点减去起点。我们将在接下来的步骤中重复使用它们:

var diffX = x2 - x1,
    diffY = y2 - y1;

步骤2:找到两点之间的角度

我们使用atan2()函数重用差异来查找角度:

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");
var x1 = 10, y1 = 10, x2 = 250, y2 = 250, radius = 150;

// Step 1: Calculate the difference between the start and end point
var diffX = x2 - x1,
    diffY = y2 - y1;

// Step 2: Find angle between the two points
var angle = Math.atan2(diffY, diffX);

// Step 3: find center of line
var mx = x1 + diffX * 0.5,
    my = y1 + diffY * 0.5;

// Step 4: produce control point
var cx = mx + radius * Math.sin(angle),
    cy = my - radius * Math.cos(angle);

// pre-viz:
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();

// result:
ctx.strokeStyle = "#000";
ctx.lineWidth = 3;
ctx.moveTo(x1, y1);
ctx.quadraticCurveTo(cx, cy, x2, y2);
ctx.stroke();

<canvas height=300></canvas>
&#13;
&#13;
&#13;