问题
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.
回答1:
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.
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)
}
}
来源:https://stackoverflow.com/questions/61536686/applying-gradient-to-uibezierpath-in-swiftui-shape