I am trying to render a linear gradient on a rectangle. Here is the code:
Rectangle()
.foregroundColor(Color.red)
.overlay(
LinearGradient(gradient: Gradient(colors: [.red, .yellow, .blue]), startPoint: .topLeading, endPoint: .bottomTrailing)
)
.frame(width: 300, height: 200)
.position(x: 170, y: 120)
When I render it on square, everything looks correct:
When I render it on a rectangle, however, it stops looking like it's going from topLeading corner to bottomTrailing. It just looks like it's the same one which was clipped:
Here is how it's rendered in svg (blue is not the same it seems, but that's not the important part), and how I want it to look in swift:
The yellow diagonal should go directly from one corner to another, since I am specifying startPoint: .topLeading, endPoint: .bottomTrailing
. It says here SwiftUI diagonal LinearGradient in a rectangle that this is a standard behaviour, and that's ok - I'm not trying to say SwiftUI renders it incorrectly, I just need a way to make it look like in svg.
What a fun problem :)
The "naive" approach would be to render the gradient as a square and then either rotate it or squeeze or stretch it to fit the rectangle. Rotating requires more maths so here's the "squeezing" version:
struct ContentView: View {
var body: some View {
Rectangle()
.overlay(
GeometryReader { g in
LinearGradient(
gradient: Gradient(colors: [.red, .yellow, .blue]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.frame(width: g.size.width, height: g.size.width)
.scaleEffect(x: 1.0, y: g.size.height / g.size.width, anchor: .top)
}
)
.frame(width: 300, height: 200)
}
}
Notes:
Please let me know if that's what you were looking for or if there is a better way to do to this!
Cheers, –Baglan