How to apply affine transformation to a gradient itself in swiftUI

Rectangle()
    .fill(
        RadialGradient.radialGradient(
            colors: [.blue, .yellow],
            center: UnitPoint(x:0.5, y:0.5),
            startRadius: 0,
            endRadius: 50)
    )
    .frame(width: 100, height: 100)
        

In the above code I have a Rectangle with simple radial gradient as follow:

I wanna apply an arbitrary transformation matrix to the gradient so I can achieve following effects:

I tried following.. but it applying the transformation matrix to frame instead of shader/gradient

Rectangle()
    .overlay(
        RadialGradient.radialGradient(
            colors: [.blue, .yellow],
            center: UnitPoint(x:0.5, y:0.5),
            startRadius: 0,
            endRadius: 50)
            .transformEffect(
                CGAffineTransform(
                    -0.5000000596046448,  0.4999999403953552,
                     -0.972577691078186, -0.9725777506828308,
                     0.5000000596046448, 1.4725778102874756)
                .translatedBy(x: -50, y: -100)
            )
    )
    .frame(width: 100, height: 100)

it result in transformation of frame intreat of shader/gradient:

Thanks in advance 🙌🏻

Replies

I tried many things but could not find how to do it directly.

So, I tried a workaround using ZStack instead of overlay.

struct ContentView: View {

    var body: some View {
        ZStack {
            Rectangle()
                .fill(.yellow)
                .frame(width: 100, height: 100)
            
            RadialGradient.radialGradient(
                colors: [.blue, .yellow],
                center: UnitPoint(x:0.5, y:0.5),
                startRadius: 0,
                endRadius: 50)
            .transformEffect(
                CGAffineTransform(
                    -0.5000000596046448,  0.4999999403953552,
                     -0.972577691078186, -0.9725777506828308,
                     0.5000000596046448, 1.4725778102874756)
                .scaledBy(x: 0.68, y: 0.68)
                .translatedBy(x: -50, y: -125)
            )
            .frame(width: 100, height: 100)
        }
    }
}

Result is close to what you expect, but the scale and translation are hardwired, they should be computed depending of the rotation…

  • Thanks a lot for your reply bro 🙌🏻... I know we can achieve in this way but it's a temperate solution...for more complex transformation it get quite headache to to this adjustment manually by trying out different values for .scaledBy(x: 0.69, y: 0.69) .translatedBy(x: -50, y: -125). etc.. But thanks for looking into it <3

Add a Comment