问题描述
我需要在 html5 画布中绘制一条完美的曲线/抛物线。给出了点的 3 {x;y} 坐标。我尝试使用 bezierCurveto 或 quadraticCurveto,但曲线不会到达中间点。
我想要的结果(蓝色虚线和蓝色曲线):Wanted result
我得到的结果:Current result
代码:
ctx.strokeStyle = '#00478a';
ctx.linewidth = 1.5;
ctx.beginPath();
ctx.moveto(x1AtRatio,30);
ctx.quadraticCurveto(criticalSectionAtRatio,100,x2AtRatio,30);
ctx.stroke();
其中 x1AtRatio - x2AtRatio - criticalSectionAtRatio 是用户输入的给定 x,30 - 100 - 30 是 y
解决方法
控制点定义斜率
您需要使用两个贝塞尔曲线,因为曲线不会通过控制点。
控制点设置曲线从最后一个点到下一个点的斜率。
示例(如下)使用两条曲线绘制抛物线。函数drawCurve()
- 我画了两次,一次缩放一次,一次正常。
- 控制点为蓝色。
- 曲线上的三个点是红色的
- 斜坡是绿色的。
例如
const ctx = canvas.getContext("2d");
// drawScaled
ctx.setTransform(2,2,-50,-55);
drawAll();
// without scale
ctx.setTransform(1,1,0);
drawAll();
function drawCurve() {
ctx.beginPath();
ctx.strokeStyle = "#000";
ctx.moveTo(100 - 30,30); // start left side
ctx.quadraticCurveTo(
100 - 30 / 2,100,// controls point sets slope out from start and into center
100,100 // center point
);
ctx.quadraticCurveTo(
100 + 30 / 2,// control point sets slope out from center and into last point
100 + 30,30 // last point
);
ctx.stroke();
}
function drawAll() {
// points on curve
drawPoint(100-30,30);
drawPoint(100,100);
drawPoint(100+30,30);
// Control points
drawPoint(100 - 30 / 2,"#00F");
drawPoint(100 + 30 / 2,"#00F");
// Draw line through all points to show slopes
drawLine(100-30,30,100 - 30 / 2,100);
drawLine(100 - 30 / 2,100);
drawLine(100,100 + 30 / 2,100);
drawLine(100 + 30 / 2,100 + 30,30);
// Draw curve
drawCurve();
}
function drawPoint(x,y,col = "red") {
ctx.fillStyle = col;
ctx.beginPath();
ctx.arc(x,Math.PI * 2);
ctx.fill();
}
function drawLine(x,x1,y1,col = "#0A08") {
ctx.strokeStyle = col;
ctx.beginPath();
ctx.lineTo(x,y);
ctx.lineTo(x1,y1);
ctx.stroke();
}
canvas {
border: 1px solid black;
}
<canvas id="canvas"></canvas>