Contents

nicklockwood/svgpath

- [Introduction](#introduction)

Scaling to Fit a Rectangle

Use the optional in rect parameter to scale the path to fit within a specific rectangle while maintaining aspect ratio:

let bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
let cgPath = try CGPath.from(svgPath: "M150 0 L75 200 L225 200 Z", in: bounds)

This is useful when you need the path to fit a specific size in your UI.

SwiftUI Integration

To use SVG paths in SwiftUI, create a Path directly from an SVG string:

let path = try Path(svgPath: "M150 0 L75 200 L225 200 Z")

Or from an existing SVGPath instance:

let path = Path(svgPath)

Creating Custom Shapes

The in rect parameter is particularly useful when implementing custom SwiftUI Shape types. The path will be automatically scaled to fit the shape's bounds:

struct Heart: Shape {
    func path(in rect: CGRect) -> Path {
        try! Path(svgPath: """
        M213.1,6.7c-32.4-14.4-73.7,0-88.1,30.6C110.6,4.9,67.5-9.5,36.9,6.7
        C2.8,22.9-13.4,62.4,13.5,110.9C33.3,145.1,67.5,170.3,125,217
        c59.3-46.7,93.5-71.9,111.5-106.1C263.4,64.2,247.2,22.9,213.1,6.7z
        """, in: rect)
    }
}

struct ContentView: View {
    var body: some View {
        Heart()
            .fill(Color.red)
            .frame(width: 200, height: 200)
    }
}

See the SVGExample project in this repository for a complete SwiftUI example app.

Converting Paths to SVG

You can convert a CGPath or SwiftUI Path to an SVGPath as follows:

let rect = CGRect(x: 0, y: 0, width: 10, height: 10)
let cgPath = CGPath(rect: rect, transform: nil)
let svgPath = SVGPath(cgPath)

To convert an SVGPath back into a string, use the string(with:) method:

let svgPath = SVGPath(cgPath)
let options = SVGPath.WriteOptions(prettyPrinted: true, wrapWidth: 80, invertYAxis: true)
let string = svgPath.string(with: options)

Cross-Platform Usage

SVGPath runs on all Apple platforms, as well as Linux and WebAssembly/Wasm. CoreGraphics and SwiftUI are not available for Linux and Wasm, but you can still parse SVG paths and work with them directly by iterating over the raw path components using the commands property:

for command in svgPath.commands {
    switch command {
    case .moveTo(let point):
        // Handle move
    case .lineTo(let point):
        // Handle line
    case .quadratic(let control, let point):
        // Handle quadratic curve
    case .cubic(let control1, let control2, let point):
        // Handle cubic curve
    case .arc(let arc):
        // Handle arc
    case .end:
        // Handle close path
    }
}

Alternatively, use the points(withDetail:) method to convert the entire path to a flat array of points for use with any graphics API:

let detail = 10 // number of sample points for curved segments
let points = svgPath.points(withDetail: detail)

Credits

The SVGPath library is primarily the work of Nick Lockwood.

(Full list of contributors)

Package Metadata

Repository: nicklockwood/svgpath

Default branch: main

README: README.md