# curves

[browser](../..) ⟩ [canvas](..) ⟩ [path]() ⟩ curves

{% tabs %}
{% tab title="🔴 主題" %}
* <mark style="color:yellow;">**related methods**</mark>
  * [arcto](arcto "mention")
* <mark style="color:yellow;">**custom extension**</mark>
  * [+ext](../+ext "mention") :star:
{% endtab %}

{% tab title="💈範例" %}
![canvas curves](https://2527454625-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MfvEFZnSBhKT6fJmus0%2Fuploads%2FYfJZEusSTWK54A4oDwbZ%2Fcanvas%20curves.png?alt=media\&token=ac07c072-ae99-482e-a5d6-588f2fc61eee)

:floppy\_disk: replit：[canvas curves](https://replit.com/@pegasusroe/canvas-curves#script.js)

⬆️ 需要： [vector](../../../appendix/custom/class/vector "mention"), [drawoncanvas2d](../+ext/drawoncanvas2d "mention"), [ctx.point](../+ext/ctx.point "mention"), [ctx.polyline](../+ext/ctx.polyline "mention")

```javascript
// ------------------
//        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);

});
```
{% endtab %}

{% tab title="📘 手冊" %}
* [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) ⟩
  * [.arc()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc) - (center, radius)\
    will <mark style="color:yellow;">**add a line**</mark> from <mark style="color:yellow;">**current point**</mark> to <mark style="color:yellow;">**arc start**</mark> <mark style="color:red;">**if current point present**</mark>.
  * [.arcTo()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arcTo) - commonly used for making <mark style="color:yellow;">**rounded corners**</mark>.
  * [.ellipse()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse)
  * [.bezierCurveTo()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo) - cubic Bezier curve
  * [.quadraticCurveTo()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/quadraticCurveTo) - quadratic Bezier curve
{% endtab %}
{% endtabs %}

