Intermediate Topics: Paths - The Powerhouse of SVG

4. Intermediate Topics: Paths - The Powerhouse of SVG

If you want to draw anything beyond simple rectangles and circles, the <path> element is your best friend. It’s the most powerful and versatile element in SVG, allowing you to create any custom shape imaginable using a series of commands. Mastering paths unlocks the full potential of SVG.

4.1 Understanding the <path> Element

The <path> element defines a complex shape by connecting a series of points using lines and curves. All the drawing instructions are contained within its d (data) attribute.

Think of it like a pen on a piece of paper:

  • You can lift the pen and move it to a new location.
  • You can put the pen down and draw a straight line.
  • You can draw various types of curves.
  • You can close the shape.

The d attribute uses a mini-language with single-letter commands, some followed by coordinates. Commands can be absolute (uppercase letters) or relative (lowercase letters).

  • Absolute commands (e.g., M): Coordinates are absolute to the SVG’s viewport (e.g., M 100 50 means move to x=100, y=50).
  • Relative commands (e.g., m): Coordinates are relative to the current pen position (e.g., m 10 20 means move 10 units right and 20 units down from the current position). Relative commands are often more convenient for drawing shapes that are offset from each other or for drawing repetitive patterns.

Let’s break down the most common path commands.

4.2 MoveTo (M or m)

The M (or m) command moves the pen to a specified point without drawing a line. It sets the starting point for a new subpath. Every path usually starts with an M command.

  • M x y: Move to absolute coordinates (x, y).
  • m dx dy: Move to (current_x + dx, current_y + dy).

Example:

<svg width="200" height="100" viewBox="0 0 200 100">
    <!-- Moves to (10,10), then to (50,50), then to (90,10) -->
    <path d="M 10 10 M 50 50 M 90 10" stroke="black" fill="none" />
</svg>

Explanation: This path only consists of M commands, so nothing is drawn. It just sets three different starting points that are not connected.

4.3 LineTo (L, l, H, h, V, v)

These commands draw straight lines.

  • L x y: Draw a straight line from the current point to absolute coordinates (x, y).
  • l dx dy: Draw a straight line from the current point to (current_x + dx, current_y + dy).
  • H x: Draw a horizontal line from the current point to absolute x-coordinate x. (y-coordinate remains the same).
  • h dx: Draw a horizontal line from the current point by dx units.
  • V y: Draw a vertical line from the current point to absolute y-coordinate y. (x-coordinate remains the same).
  • v dy: Draw a vertical line from the current point by dy units.

Example:

<svg width="250" height="150" viewBox="0 0 250 150">
    <!-- A simple square -->
    <path
        d="M 20 20 L 120 20 L 120 120 L 20 120 Z"
        fill="lightblue"
        stroke="blue"
        stroke-width="2"
    />

    <!-- Using H and V for a star shape -->
    <path
        d="M 180 20 H 220 V 60 H 140 Z"
        fill="lightgreen"
        stroke="green"
        stroke-width="2"
    />
</svg>

Explanation: The first path creates a square using absolute L commands. The second path creates a shape using H and V for horizontal and vertical lines.

4.4 ClosePath (Z or z)

The Z (or z) command closes the current subpath by drawing a straight line from the current point back to the starting point of the current subpath. It’s case-insensitive as it takes no parameters.

Example:

<svg width="200" height="150" viewBox="0 0 200 150">
    <!-- A triangle drawn with L commands and closed with Z -->
    <path d="M 100 20 L 180 130 L 20 130 Z" fill="orange" stroke="black" stroke-width="2" />
</svg>

4.5 Bézier Curves

Bézier curves are fundamental for drawing smooth, flowing shapes. SVG supports two types: quadratic and cubic.

4.5.1 Quadratic Bézier Curves (Q or q, T or t)

Quadratic Bézier curves have one control point that determines the curve’s shape.

  • Q cx cy x y: Draw a quadratic Bézier curve from the current point to (x, y) using (cx, cy) as the control point.
  • q dcx dcy dx dy: Relative version.
  • T x y: Draw a smooth quadratic Bézier curve from the current point to (x, y). The control point is a reflection of the control point of the previous Q or T command. This is useful for chaining smooth curves.
  • t dx dy: Relative version.

Example:

<svg width="250" height="200" viewBox="0 0 250 200">
    <!-- A simple quadratic curve -->
    <path
        d="M 20 100 Q 100 20 180 100"
        fill="none"
        stroke="red"
        stroke-width="2"
    />
    <!-- The control point for visualization -->
    <circle cx="100" cy="20" r="3" fill="red" />

    <!-- Smooth quadratic curves -->
    <path
        d="M 20 150 Q 70 80 120 150 T 220 150"
        fill="none"
        stroke="blue"
        stroke-width="2"
    />
    <circle cx="70" cy="80" r="3" fill="blue" />
    <!-- The reflected control point would be at (170, 80) for the second curve -->
</svg>

4.5.2 Cubic Bézier Curves (C or c, S or s)

Cubic Bézier curves are more flexible as they use two control points, allowing for more complex curve shapes.

  • C c1x c1y c2x c2y x y: Draw a cubic Bézier curve from the current point to (x, y) using (c1x, c1y) as the first control point and (c2x, c2y) as the second.
  • c dc1x dc1y dc2x dc2y dx dy: Relative version.
  • S c2x c2y x y: Draw a smooth cubic Bézier curve. The first control point is a reflection of the second control point of the previous C or S command.
  • s dc2x dcy dx dy: Relative version.

Example:

<svg width="300" height="200" viewBox="0 0 300 200">
    <!-- A simple cubic curve -->
    <path
        d="M 20 100 C 60 20 140 20 180 100"
        fill="none"
        stroke="green"
        stroke-width="2"
    />
    <!-- Control points for visualization -->
    <circle cx="60" cy="20" r="3" fill="green" />
    <circle cx="140" cy="20" r="3" fill="green" />

    <!-- Smooth cubic curves (S command) -->
    <path
        d="M 20 150 C 70 80 120 80 170 150 S 270 150"
        fill="none"
        stroke="purple"
        stroke-width="2"
    />
    <!-- Control points -->
    <circle cx="70" cy="80" r="3" fill="purple" />
    <circle cx="120" cy="80" r="3" fill="purple" />
    <!-- Reflected control point for S would be at (220, 80) -->
</svg>

4.6 Arc Curves (A or a)

The A command draws elliptical arcs, allowing you to draw parts of circles or ellipses. This command is the most complex due to its many parameters.

  • A rx ry x-axis-rotation large-arc-flag sweep-flag x y

Let’s break down the parameters:

  1. rx ry: The x and y radii of the ellipse of which the arc is a segment.
  2. x-axis-rotation: The rotation of the ellipse around its x-axis in degrees.
  3. large-arc-flag: 0 for a small arc (less than or equal to 180 degrees), 1 for a large arc (greater than 180 degrees). There are always two possible arcs between two points; this flag tells SVG which one to choose.
  4. sweep-flag: 0 for an arc that sweeps counter-clockwise, 1 for an arc that sweeps clockwise. Again, two possible arcs.
  5. x y: The absolute coordinates of the endpoint of the arc.

Example:

<svg width="250" height="200" viewBox="0 0 250 200">
    <!-- An arc segment -->
    <path
        d="M 20 100 A 80 80 0 0 1 120 100"
        fill="none"
        stroke="teal"
        stroke-width="3"
    />

    <!-- Another arc, with different flags -->
    <path
        d="M 130 100 A 80 80 0 1 1 230 100"
        fill="none"
        stroke="orange"
        stroke-width="3"
    />

    <!-- A full circle using two arcs (M x y A r r 0 1 1 x y A r r 0 1 1 x y Z) -->
    <!-- M 100 50 A 50 50 0 1 1 100 51 Z (this is a common trick to ensure a full circle as start and end points are almost the same) -->
    <path
        d="M 50 50 A 40 40 0 1 1 50 50.001 Z"
        transform="translate(100,0)"
        fill="lightgray"
        stroke="gray"
        stroke-width="2"
    />
</svg>

Explanation for the full circle trick: A single arc command cannot draw a full circle because an arc requires distinct start and end points. If the start and end points are identical, the path becomes undefined or invisible. By making the endpoint slightly different (e.g., 50 50.001), it allows the arc to render a complete circle, which Z then officially closes. transform="translate(100,0)" moves this circle for better visibility in the example.

Exercises/Mini-Challenges

  1. Draw a Heart Shape:

    • Using a combination of M, L, and C (cubic Bézier) commands, try to draw a heart shape. This is a classic path challenge!
    • Hint: A heart can be approximated by two cubic Bézier curves for the top lobes and a single L or Z for the bottom point. You can also combine Q commands for a simpler approximation.
  2. A Simple Cloud:

    • Create a cloud shape using multiple Q (quadratic Bézier) commands, chaining them with T for smooth transitions.
    • Don’t forget to Z to close your path if you want it filled.
  3. Wavy Line:

    • Draw a continuous wavy line using Q or C commands, making sure the curves flow smoothly into each other. Use stroke but fill="none".
    • Experiment with stroke-linecap="round" and stroke-linejoin="round" to see how they affect the wave.
  4. Pac-Man or Pie Slice:

    • Use the A (arc) command to draw a Pac-Man shape or a slice of pie. This will require some careful thought about your rx, ry, large-arc-flag, and sweep-flag values.
    • You’ll likely start with an M to the center, L out to the edge of the slice, then A for the arc, and Z back to the center.
  5. Recreate an Arrow:

    • Create an arrow icon purely using the <path> element and L, H, V, and Z commands. No <line> or <polygon>!
    • Try a simple right-pointing arrow.