✨curves
Last updated
Last updated
browser ⟩ canvas ⟩ path ⟩ curves
related methods
custom extension
💾 replit:canvas curves
⬆️ 需要: Vector, drawOnCanvas2D(), ctx.point(), ctx.polyline()
// ------------------
// main
// ------------------
const { PI } = Math;
// degrees
function deg(x) { return PI * x / 180 }
// draw on canvas
drawOnCanvas2D('#playground', (c) => {
const center = vec(75, 100);
const R = 50, r = 35, dx = 20;
const d = 2 * R + dx;
const v = vec(d, 0); // translation vector
const wholeRound = [0, 2 * PI];
c.fillStyle = "pink"; // fill color
c.lineWidth = 4; // stroke width
// circle
// --------------------------------------
c.beginPath();
// no current point, so no straight line
// from current point to start of arc.
c.arc(...center.coords, R, ...wholeRound);
c.fill();
c.stroke();
// ellipse
// --------------------------------------
c.beginPath();
// Start new path not connected to the circle
const c1 = center.add(v);
c.ellipse(...c1.coords, R, r, deg(15), ...wholeRound);
c.fillStyle = "#cfc";
c.fill();
c.stroke();
// wedge
// --------------------------------------
const c2 = c1.add(v);
const wedgeRange = [deg(-60), 0];
c.beginPath();
c.moveTo(...c2.coords); // current point
// ⭐ arc() adds a line from current point to arc start.
c.arc(...c2.coords, R, ...wedgeRange, true); // counterclockwise
c.closePath(); // add radius back to center
// another (smaller) wedge
const c3 = c2.add(polar(dx, deg(-30)));
c.moveTo(...c3.coords);
c.arc(...c3.coords, 42, ...wedgeRange);
c.closePath();
// rounded sqaure
// --------------------------------------
const P0 = c2.add(v).plus(0, -R); // top middle
const P1 = P0.plus(R, 0); // top right
const P2 = P1.plus(0, 2 * R); // bottom right
const P3 = P2.plus(-2 * R, 0); // bottom left
const P4 = P3.plus(0, -2 * R); // top left
// begin in the middle of the top edge.
c.moveTo(...P0.coords);
// use arcTo() for rounded corners.
c.arcTo(...P1.coords, ...P2.coords, r);
c.arcTo(...P2.coords, ...P3.coords, r);
c.arcTo(...P3.coords, ...P4.coords, r);
c.arcTo(...P4.coords, ...P0.coords, r);
c.closePath();
c.fillAndStroke();
// Bezier curve
// --------------------------------------
// quadratic Bezier
const B1 = P1.plus(dx, dx); // start
const B2 = B1.plus(25, -50); // control point
const B3 = B1.plus(100, 0); // end
c.moveTo(...B1.coords);
c.quadraticCurveTo(...B2.coords, ...B3.coords);
// cubic Bezier
const Q1 = P2.plus(dx, -dx);
const Q4 = Q1.plus(100, 0);
const Q2 = Q1.plus(25, -50);
const Q3 = Q4.plus(-25, 50);
c.moveTo(...Q1.coords);
c.bezierCurveTo(...Q2.coords, ...Q3.coords, ...Q4.coords);
// fill and stroke rest curves
c.fillStyle = "#ccf";
c.fillAndStroke();
// control points
[
[B1, B2, B3],
[Q1, Q2, Q3, Q4],
].forEach(pts => {
c.polyline(pts);
pts.forEach(p => c.point(...p.coords));
})
// debug info
console.log(Q4);
});
.arc() - (center, radius) will add a line from current point to arc start if current point present.
.arcTo() - commonly used for making rounded corners.
.bezierCurveTo() - cubic Bezier curve
.quadraticCurveTo() - quadratic Bezier curve