George
George

Reputation: 30401

Text opacity gradient

I'm looking to make text to appear to fade out on the edge. Here is what I have so far:

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.red

            Text("Hello world!")
//                .blendMode(.luminosity) // <- Here?
                .overlay(
                    LinearGradient(colors: [.white.opacity(0), .white], startPoint: .leading, endPoint: .trailing)
                        .frame(width: 50)
//                        .blendMode(.exclusion) // <- Here?
                        .frame(maxWidth: .infinity, alignment: .trailing)
                )
        }
    }
}

Producing:

Produced result

You can see the white gradient over the right side of the text. This should act like an opacity filter. Where the white isn't over, the text is fully visible. Below the white, the text should be completely transparent. It should be a gradual transition by using the gradient.

I think this can be solved using blendMode(_:), but I'm not too sure. I don't know which mode to use, nor where to apply it.

The solution to this should work in light & dark mode (i.e. the text may be black or white). The actual background behind is not a constant color (such as red) so using a red gradient overlay is not what I'm looking for.

Upvotes: 3

Views: 885

Answers (2)

George
George

Reputation: 30401

With thanks to aheze's answer, it now works.

Just a small thing I'll add, to show the way to get the exact same results as in the question (because mask sort of inverts it):

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.red

            Text("Hello world!")
                .mask(
                    HStack(spacing: 0) {
                        Color.white

                        LinearGradient(colors: [.white, .clear], startPoint: .leading, endPoint: .trailing)
                            .frame(width: 50)
                    }
                )
        }
    }
}

Result:

Result

Upvotes: 1

aheze
aheze

Reputation: 30336

Just use .mask instead.

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.red
            
            Text("Hello world!")
            
            /// for iOS 14 and below, replace { } with ( )
            .mask {
                ///                             no need for .opacity, just use .clear
                LinearGradient(colors: [.white, .clear], startPoint: .leading, endPoint: .trailing)
            }
        }
    }
}

Result:

Text fades out on right

Upvotes: 9

Related Questions