Nadir Muzaffar
Nadir Muzaffar

Reputation: 4842

Applying gradient to UIBezierPath in SwiftUI Shape

I'm trying to accomplish the following:

struct MultiSegmentPaths: Shape {
  func path(in rect: CGRect) -> Path {
    let path1 = UIBezierPath()
    // apply gradient to path 1
    let path2 = UIBezierPath()
    // apply gradient to path 2

    return Path(path1.append(path2).cgPath)
  }
}

Now I thought I could wrap each segment with Path, but that returns some View which means I can't append the two together.

And applying a gradient directly to UIBezierPath requires having access to context - which isn't passed in via the path(CGRect) -> Path method.

Finally the reason for creating the two paths within the same Shape is because I need to scale them while maintaining their offsets to each other.

Upvotes: 1

Views: 1534

Answers (1)

Asperi
Asperi

Reputation: 257693

The UIBezierPath(UIKIt) and Path(SwiftUI) are different things... To create Path you have to use its own instruments. Next, the fill operation (w/ gradient or anything) is drawing time operation, not part of path/shape creation.

Here is some example of combining to shapes filled by gradients. Tested with Xcode 11.4.

demo

struct DemoShape1: Shape {
    func path(in rect: CGRect) -> Path {
        return Path { path in
            path.addRect(rect)
        }
    }
}

struct DemoShape2: Shape {
    func path(in rect: CGRect) -> Path {
        return Path { path in
            path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.size.height/2, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 360), clockwise: true)
        }
    }
}

struct DemoCombinedShape: View {
    var gradient1 = LinearGradient(gradient: Gradient(colors:[.blue, .yellow]), startPoint: .top, endPoint: .bottom)
    var gradient2 = LinearGradient(gradient: Gradient(colors:[.red, .black]), startPoint: .leading, endPoint: .trailing)

    var body: some View {
        // both shapes are rendered in same coordinate space
        DemoShape1().fill(gradient1)
            .overlay(DemoShape2().fill(gradient2))
    }
}

struct TestCombinedShape_Previews: PreviewProvider {
    static var previews: some View {
        DemoCombinedShape()
            .frame(width: 400, height: 300)
    }
}

Upvotes: 1

Related Questions