Skip to content

Drawing Paths

Paths are the foundation of complex shapes in FxCanvas, allowing you to create custom geometry from lines, curves, and arcs. Unlike simple shapes like rectangles or ellipses, paths give you complete control over the outline of your drawings.

Understanding Paths

A path is a sequence of connected points and curves that define a shape's boundary. You build paths step by step, then fill them with color or stroke their outlines. Paths are essential for creating irregular shapes, logos, icons, and organic forms.

Paths are frequently stroked for outlines; see Working with Strokes.

Creating and Building Paths

All path operations start with beginPath(), which clears any existing path and starts a new one.

javascript
import { CanvasEncoder } from 'fxcanvas';

const canvas = new CanvasEncoder(400, 200);

// Start a new path
canvas.beginPath();

Moving the Pen

The moveTo(x, y) method moves the drawing cursor to a new position without drawing.

javascript
canvas.beginPath();
canvas.moveTo(50, 50); // Move to starting point

Drawing Straight Lines

The lineTo(x, y) method draws a straight line from the current position to the specified point.

javascript
canvas.beginPath();
canvas.moveTo(50, 50);
canvas.lineTo(150, 50);  // Draw horizontal line
canvas.lineTo(150, 100); // Draw vertical line
canvas.stroke();

Path Building Methods

FxCanvas provides convenient methods to add common shapes directly to paths, combining the simplicity of shape methods with the flexibility of custom paths.

Adding Rectangles

The rect(x, y, width, height) method adds a rectangular subpath to the current path:

javascript
canvas.beginPath();
canvas.rect(50, 50, 100, 100); // Add rectangle to path
canvas.stroke();

This creates a rectangular outline that can be combined with other path elements. For basic rectangle drawing without paths, see Drawing Rectangles.

Adding Rounded Rectangles

The roundRect(x, y, width, height, radii?) method adds a rounded rectangular subpath:

javascript
canvas.beginPath();
canvas.roundRect(50, 50, 200, 100, 20); // Uniform corner radius
canvas.fill();

// Different radii per corner
canvas.beginPath();
canvas.roundRect(50, 50, 200, 100, [10, 20, 30, 40]); // [TL, TR, BR, BL]
canvas.stroke();

Rounded rectangles in paths allow for complex shapes with smooth corners. For direct rounded rectangle drawing, see Drawing Rectangles.

Adding Ellipses

The ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle) method adds an elliptical arc to the path:

javascript
canvas.beginPath();
// Full ellipse centered at (100, 100) with radii 50x30
canvas.ellipse(100, 100, 50, 30, 0, 0, Math.PI * 2);
canvas.stroke();

// Partial ellipse (semicircle)
canvas.beginPath();
canvas.ellipse(100, 100, 50, 30, 0, 0, Math.PI); // Top half
canvas.stroke();

The ellipse method provides full control over elliptical shapes in paths. For basic ellipse drawing, see Drawing Ellipses.

Paths can be used for clipping; see Clipping and Masking.

Drawing Quadratic Curves

Quadratic curves create smooth, single-control-point curves, perfect for gentle bends.

The quadraticCurveTo(cpx, cpy, x, y) method draws a curve to the endpoint using one control point.

javascript
canvas.beginPath();
canvas.moveTo(50, 100);
canvas.quadraticCurveTo(100, 50, 150, 100); // Control point at (100, 50)
canvas.stroke();

The control point pulls the curve toward it, creating a smooth bend.

Drawing Bézier Curves

Bézier curves offer more complex curves with two control points, allowing for S-shaped curves and precise control.

The bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) method draws a curve using two control points.

javascript
canvas.beginPath();
canvas.moveTo(50, 100);
canvas.bezierCurveTo(75, 50, 125, 150, 150, 100); // Two control points
canvas.stroke();

The first control point affects the start of the curve, the second affects the end.

Closing Paths

The closePath() method draws a line back to the path's starting point, creating a closed shape.

javascript
canvas.beginPath();
canvas.moveTo(50, 50);
canvas.lineTo(150, 50);
canvas.lineTo(150, 100);
canvas.closePath(); // Draws line back to (50, 50)
canvas.stroke();

Filling and Stroking Paths

Once you've built a path, you can fill it or stroke its outline.

Filling Paths

The fill() method fills the path with the current fill style.

javascript
canvas.beginPath();
canvas.moveTo(50, 50);
canvas.lineTo(150, 50);
canvas.lineTo(100, 100);
canvas.closePath();

canvas.setFillStyle(new Color(173, 216, 230))); // lightblue
canvas.fill();

Paths support advanced compositing modes; see Composite Operations.

Stroking Paths

The stroke() method draws the path outline with the current stroke settings.

javascript
canvas.beginPath();
canvas.moveTo(50, 50);
canvas.lineTo(150, 50);
canvas.lineTo(100, 100);
canvas.closePath();

canvas.setStrokeStyle(new Color(0, 0, 139))); // darkblue
canvas.setLineWidth(3);
canvas.stroke();

Combining Fill and Stroke

javascript
canvas.setFillStyle(new Color(255, 255, 0))); // yellow
canvas.setStrokeStyle(new Color(255, 165, 0))); // orange
canvas.setLineWidth(2);

canvas.beginPath();
// ... build path ...
canvas.closePath();

canvas.fill();
canvas.stroke();

Advanced Path Techniques

Drawing Arcs

The arc(x, y, radius, startAngle, endAngle, anticlockwise?) method adds a circular arc to the path.

javascript
canvas.beginPath();
canvas.arc(100, 100, 50, 0, Math.PI * 1.5); // 270-degree arc
canvas.stroke();

Complex Shapes

javascript
// Draw a star
canvas.beginPath();
const centerX = 100, centerY = 100;
const outerRadius = 50, innerRadius = 25;
const spikes = 5;

for (let i = 0; i < spikes * 2; i++) {
    const radius = i % 2 === 0 ? outerRadius : innerRadius;
    const angle = (i * Math.PI) / spikes;
    const x = centerX + Math.cos(angle) * radius;
    const y = centerY + Math.sin(angle) * radius;
    if (i === 0) canvas.moveTo(x, y);
    else canvas.lineTo(x, y);
}
canvas.closePath();
canvas.setFillStyle(new Color(255, 215, 0))); // gold
canvas.fill();

Path Clipping

Paths can be used to create clipping regions that limit drawing to within the path.

javascript
// Create clipping path
canvas.beginPath();
canvas.arc(100, 100, 50, 0, Math.PI * 2);
canvas.clip();

// Subsequent drawing is clipped to the circle
canvas.setFillStyle(new Color(255, 0, 0))); // red
canvas.fillRect(50, 50, 100, 100); // Only the circular portion appears

Path Reusability

Complex paths can be built in functions for reuse:

javascript
function drawHeart(encoder, x, y, size) {
    canvas.beginPath();
    canvas.moveTo(x, y + size / 4);
    canvas.quadraticCurveTo(x, y, x + size / 4, y);
    canvas.quadraticCurveTo(x + size / 2, y, x + size / 2, y + size / 4);
    canvas.quadraticCurveTo(x + size / 2, y, x + size * 3/4, y);
    canvas.quadraticCurveTo(x + size, y, x + size, y + size / 4);
    canvas.quadraticCurveTo(x + size, y + size / 2, x + size / 2, y + size);
    canvas.quadraticCurveTo(x, y + size / 2, x, y + size / 4);
    canvas.closePath();
}

drawHeart(encoder, 50, 50, 50);
canvas.setFillStyle(new Color(255, 0, 0))); // red
canvas.fill();

Mastering paths unlocks the full creative potential of FxCanvas, allowing you to create any shape imaginable.