我需要使用画布,我需要使用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)的任何距离。
使用简单的斜率,就像在我的例子中一样,它可能可以解决但是对角线的斜率可以是任何东西,取决于起点和终点。起点和终点是根据用户输入计算出来的,因此控制点需要从中动态计算自己。
我花了好几个月的时间,凭借我对画布的了解,我得到了无处可去的地方。
非常感谢任何帮助!
提前感谢!
麦克
答案 0 :(得分:3)
简单地从终点减去起点。我们将在接下来的步骤中重复使用它们:
var diffX = x2 - x1,
diffY = y2 - y1;
我们使用atan2()
函数重用差异来查找角度:
var angle = Math.atan2(diffY, diffX);
使用线性插值我们再次重复使用表示中心点的标准化值的差异:
var mx = x1 + diffX * 0.5,
my = y1 + diffY * 0.5;
最后,通过使用半径为切线角的中点将所有内容放在一起(这里的半径是从中点开始的长度,以像素为单位)。
我们在这里反转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;