Javascript 如何平滑地连接两条贝塞尔曲线&;连续使用HTML5画布
我试图把两条独立的贝塞尔曲线连接成一条连续曲线。目前,我所拥有的是这样的: 问题是它们没有连接在一起,因此它们相交的点看起来尖锐/尖锐,而不是弯曲和平滑。我查阅了P5.js中连接贝塞尔曲线的文档,但不确定如何将其转换为HTML5画布。如何连接这两条贝塞尔曲线,使它们看起来像一条平滑连续的曲线 这是我的代码:Javascript 如何平滑地连接两条贝塞尔曲线&;连续使用HTML5画布,javascript,canvas,html5-canvas,Javascript,Canvas,Html5 Canvas,我试图把两条独立的贝塞尔曲线连接成一条连续曲线。目前,我所拥有的是这样的: 问题是它们没有连接在一起,因此它们相交的点看起来尖锐/尖锐,而不是弯曲和平滑。我查阅了P5.js中连接贝塞尔曲线的文档,但不确定如何将其转换为HTML5画布。如何连接这两条贝塞尔曲线,使它们看起来像一条平滑连续的曲线 这是我的代码: const canvas = document.getElementById('canvas'); const c = canvas.getContext("2d");
const canvas = document.getElementById('canvas');
const c = canvas.getContext("2d");
width = 800;
height = 500;
canvas.width = width;
canvas.height = height;
let face;
let centerX = width / 2;
let centerY = height / 3;
setup();
function setup() {
c.clearRect(0, 0, canvas.width, canvas.height);
face = new Face();
draw();
};
function draw() {
setBackground(`rgba(250, 250, 250, 1)`);
c.beginPath();
c.moveTo(centerX - face.hsx, centerY + face.hsy);
c.bezierCurveTo(centerX - face.hcp1x / 10, centerY - face.hsy2,
centerX + face.hcp1x / 10, centerY - face.hsy2,
centerX + face.hsx, centerY + face.hsy);
c.moveTo(centerX - face.hsx, centerY + face.hsy);
c.bezierCurveTo(centerX - face.hcp1x, centerY + face.hcp1y,
centerX + face.hcp1x, centerY + face.hcp1y,
centerX + face.hsx, centerY + face.hsy);
c.stroke();
c.fillStyle = (`rgba(25, 250, 211, 0)`);
c.fill();
}
function setBackground(color) {
c.fillStyle = color;
c.fillRect(0, 0, width, height);
}
function Face() {
this.hsx = 150;
this.hsy = 0;
this.hsy2 = 120;
this.hcp1x = 120;
this.hcp1y = 250;
}
公切线
要平滑连接两个贝塞尔曲线,需要使公共点的直线平行,从而定义两个贝塞尔曲线端点和起点处的切线相同
下图说明了这一点
由两个控制点(C2、C1)和公共点(p)定义的直线是曲线在p处的切线。线段的长度没有约束
怎么用?
有几十种方法可以做到这一点,如何做到这一点取决于曲线的要求、曲线的类型等等
例子
我不打算给出一个完整的例子,因为它需要理解向量数学,并且假设你不熟悉向量数学,那么它的解决方案将是巨大的
因此,最基本的伪代码示例使用前面的控件和端点来计算下一个控件点<代码>?表示不受保持直线平行所需约束约束约束的未知数
// From illustration in answer
corner = ? // Distance to next control point as fraction of distance
// from previous control point
C2 = {x:?, y:?} // Last control point of previous bezier
P = {x:?, y:?} // Start of next bezier
C1 = { // Next control point along line from previous and scaled
x: P.x + (P.x - C2.x) * corner,
y: P.y + (P.y - C2.y) * corner,
}
// two beziers with common point P
ctx.bezierCurveTo(?,?, C2.x, C2.y, P.x, P.y)
ctx.bezierCurveTo(C1.x, C1.y, ?, ?, ?, ?)
公切线
要平滑连接两个贝塞尔曲线,需要使公共点的直线平行,从而定义两个贝塞尔曲线端点和起点处的切线相同
下图说明了这一点
由两个控制点(C2、C1)和公共点(p)定义的直线是曲线在p处的切线。线段的长度没有约束
怎么用?
有几十种方法可以做到这一点,如何做到这一点取决于曲线的要求、曲线的类型等等
例子
我不打算给出一个完整的例子,因为它需要理解向量数学,并且假设你不熟悉向量数学,那么它的解决方案将是巨大的
因此,最基本的伪代码示例使用前面的控件和端点来计算下一个控件点<代码>?表示不受保持直线平行所需约束约束约束的未知数
// From illustration in answer
corner = ? // Distance to next control point as fraction of distance
// from previous control point
C2 = {x:?, y:?} // Last control point of previous bezier
P = {x:?, y:?} // Start of next bezier
C1 = { // Next control point along line from previous and scaled
x: P.x + (P.x - C2.x) * corner,
y: P.y + (P.y - C2.y) * corner,
}
// two beziers with common point P
ctx.bezierCurveTo(?,?, C2.x, C2.y, P.x, P.y)
ctx.bezierCurveTo(C1.x, C1.y, ?, ?, ?, ?)