I want to draw a slightly bent line using bezier curve.
This is the bezier curve function:
function bezierCurve(controlPoint1, controlPoint2, line) { }
I don't know how to set control points to achieve a slightly bent line for any line.
I tried to find the perpendicular point of this line:
function Line(a, b) {
let mid = [(a[0] + b[0]) / 2,
(a[1] + b[1]) / 2];
let dX = b[0] - a[0],
dY = b[1] - a[1];
this.perpPoint = (y) => {
let x1 = mid[0],
y1 = mid[1],
x;
if (dX === 0 || dY === 0) {
x = y;
y = y1;
return [x, y];
}
let m = dX / dY;
let perpendicularM = - 1 / m;
// y - y1 = m(x - x1)
// x = (y - y1) / m + x1
x = (y - y1) / m + x1;
return [x, y];
};
And use that somehow to find the points just above the midpoint of the line as control points, but didn't work.
The function
function bezierCurve(controlPoint1, controlPoint2, line) { }
Suggest that the curve is a cubic bezier (two control points) the function you give looks like its only finding a point mid way and offset some fixed amount. you will need more control over where the point is in relationship to the line.
The following function will give you a little more control letting you specifty where along the line you want the point and how far that point should be from the line.
The argument along
and dist
are fractions of a line such the along = 0.5
is halfway and dist = 0.2
is 1/5th the length of the line away. dist > 0
and the point is offset to the right of the line dist < 0
and the offset is to the left (Y axis pointing down)
function pointFromLine(along, dist, p1, p2, res = {}) {
const dx = p2.x - p1.x;
const dy = p2.y - p1.y;
res.x = p1.x + dx * along - dy * dist;
res.y = p1.y + dy * along + dx * dist;
return res;
}
To find the mid point 1/5th the line length away from the center
const p1 = {x: 10, y: 10};
const p2 = {x: 510, y: 310};
const offset = pointFromLine(0.5, 0.2, p1, p2);
To find two control point for a cubic bezier.
const p1 = {x: 10, y: 10};
const p2 = {x: 510, y: 310};
const cp1 = pointFromLine(0.333, 0.2, p1, p2); // 1/3rd dist from start
const cp2 = pointFromLine(1 - 0.333, 0.2, p1, p2); // equal dist (1/3rd) from end of line
The following snippet show the function used to create a symmetrical curve for a cubic bezier. Move the slider to control the dist along the line and the dist offset from the line
function pointFromLine(along, dist, p1, p2, res = {}) { const dx = p2.x - p1.x; const dy = p2.y - p1.y; res.x = p1.x + dx * along - dy * dist; res.y = p1.y + dy * along + dx * dist; return res; } const p1 = {x: 40, y: 40}; const p2 = {x: 160, y: 160}; const cp1 ={x: 0, y: 0}; const cp2 ={x: 0, y: 0}; const ctx = canvas.getContext("2d"); update(); function drawPoint(p) { ctx.beginPath(); ctx.arc(px, py, 4, 0, Math.PI * 2); ctx.fill(); } function drawLine(p1, p2) { ctx.lineWidth = 1; ctx.beginPath(); ctx.lineTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); } function drawCubicBezier(p1, p2, cp1, cp2) { ctx.lineWidth = 3; ctx.beginPath(); ctx.lineTo(p1.x, p1.y); ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, p2.x, p2.y); ctx.stroke(); drawLine(p1,cp1); drawLine(p2,cp2); drawPoint(p1); drawPoint(p2); drawPoint(cp1); drawPoint(cp2); } alongIn.addEventListener("input", update); distIn.addEventListener("input", update); function update() { const a = alongIn.value * 1; const d = distIn.value * 1; info.textContent = `Along: ${a.toFixed(2)} Offset: ${d.toFixed(2)}` ctx.clearRect(0,0,200,200); drawCubicBezier( p1, p2, pointFromLine(a , d, p1, p2, cp1), pointFromLine(1 - a, d, p1, p2, cp2) ); }
canvas { border: 1px solid black; }
Dist along: <input id="alongIn" type="range" min="-1" max="2" step="0.01" value="0.3"/> Dist out: <input id="distIn" type="range" min="-1" max="2" step="0.01" value="0.3"/> <div id="info"> </div> <canvas id="canvas" width="200" height="200" ></canvas>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.