SwiftUI How to Fade an Image out from the bottom Edge - swiftui

Basically what Im trying to achieve is this:
To fade an image out from the top to bottom. I tried to do it with overlays but it simply does not look good

Here is a working view to fade an image out from the top to the bottom.
Lmk if it works!
Source Code
struct ContentView: View {
var body: some View {
VStack {
Image("Explore")//Your Image
.resizable()
}
//We can use the LinearGradient in the mask modifier to fade it top to bottom
.mask(LinearGradient(gradient: Gradient(stops: [
.init(color: .black, location: 0),
.init(color: .clear, location: 1),
.init(color: .black, location: 1),
.init(color: .clear, location: 1)
]), startPoint: .top, endPoint: .bottom))
.padding()
.frame(width: 400, height: 400)
}
}
Preview

Related

How to make a border from a view in SwiftUI?

I'd like to make a 2px border from a view, but the border only accepts a ShapeStyle. I'm trying to do something like:
let specialRadialGradient = GeometryReader { geometry in
RadialGradient(
gradient: Gradient(
stops: [
.init(color: Color("gradient1").opacity(0.5), location: 0),
.init(color: Color("gradient2").opacity(0.5), location: 1)
]
),
center: .init(x: 0.1432, y: 0.7254
startRadius: .zero,
endRadius: geometry.size.width * 0.75
)
.background(Color.brandPrimary)
}
Text("Abc")
.frame(maxWidth: .infinity)
.padding()
.border(specialRadialGradient, 2)
However, since the specialRadialGradient view is wrapped in a GeometryReader to handle the radial gradient properly in all ratio sizes, it doesn't compile. How can I cut out a 2px border out of specialRadialGradient and apply it to the background of the text?
Instead of border it can be done with composition of background and blending mode.
Here is a demo of possible approach. Tested with Xcode 14 / iOS 16
*(gradient colours just replicated for demo)
let borderWidth = 2.0
Text("Abc")
.frame(maxWidth: .infinity)
.padding()
.background(
specialRadialGradient
.overlay(Rectangle().padding(borderWidth) // << here !!
.blendMode(.destinationOut))
.compositingGroup() // << important !!
)
Test code on GitHub

radial gradient shape in swiftui

hey everyone, I designed some stuff in figma and now that Im trying to transfer everything to swiftui I'm having some troubles. Does anyone know how I can make this ellipse shaped gradient in swiftui? I tried the swuiftui inspector but it just gave me a circular shape. Thanks for the help.
iOS15 only :
struct ContentView: View {
var body: some View {
Rectangle()
.fill(
.ellipticalGradient(
colors: [.red, .orange, .yellow],
center: .center,
startRadiusFraction: 0.2,
endRadiusFraction: 0.6
)
)
}
}
or :
struct ContentView2: View {
let gradient = Gradient(stops:
[.init(color: .red, location: 0.2),
.init(color: .orange, location: 0.6),
.init(color: .yellow, location: 0.8)])
var body: some View {
Rectangle()
.fill(
.elliptical(gradient,
center: .center,
startRadiusFraction: 0.1,
endRadiusFraction: 0.6)
)
}
}
You can use RadialGradient by applying scaleEffect modifier to shrink it:
struct ContentView: View {
let gradient = Gradient(
stops: [
.init(color: .green.opacity(0.4), location: 0),
.init(color: .green.opacity(0.5), location: 0.7),
.init(color: .green.opacity(0), location: 1),
]
)
var body: some View {
GeometryReader { geometry in
Rectangle()
.fill(
RadialGradient(
gradient: gradient,
center: .center,
startRadius: 0,
endRadius: geometry.size.width / 2
)
)
.scaleEffect(x: 1, y: geometry.size.height / geometry.size.width, anchor: .center)
}
}
}
Since iOS 15 you can get rid of both GeometryReader and scaleEffect using EllipticalGradient, so it may be more performant, or at least less code:
struct ContentView: View {
let gradient = Gradient(
stops: [
.init(color: .green.opacity(0.4), location: 0),
.init(color: .green.opacity(0.5), location: 0.7),
.init(color: .green.opacity(0), location: 1),
]
)
var body: some View {
Rectangle()
.fill(
EllipticalGradient(
gradient: gradient,
center: .center
)
)
}
}
Both variants looks totally the same:

Swiftui - Add blur linear gradient

I would like to add a white text on the top of an image.
My strategy will be to add a gradient that will be blurred at the text zone (please check the attached picture)
Anyone got an idea how to do this?
How's this?
For the blur effect, just use the .blur() modifier - no need for a separate image that's blurred.
struct ContentView: View {
let gradient = LinearGradient(
gradient: Gradient(stops: [
.init(color: .purple, location: 0),
.init(color: .clear, location: 0.4)
]),
startPoint: .bottom,
endPoint: .top
)
var body: some View {
Image("Background")
.resizable()
.aspectRatio(contentMode: .fit)
.overlay(
ZStack(alignment: .bottom) {
Image("Background")
.resizable()
.blur(radius: 20) /// blur the image
.padding(-20) /// expand the blur a bit to cover the edges
.clipped() /// prevent blur overflow
.mask(gradient) /// mask the blurred image using the gradient's alpha values
gradient /// also add the gradient as an overlay (this time, the purple will show up)
HStack {
Image("Icon") /// app icon
.resizable()
.frame(width: 64, height: 64)
VStack(alignment: .leading) {
Text("Classroom of the Elite")
.bold()
Text("Horikita best girl")
.opacity(0.75)
}
.frame(maxWidth: .infinity, alignment: .leading) /// allow text to expand horizontally
Button { } label: {
Text("GET")
.bold()
.padding(8)
.background(Color.gray)
.cornerRadius(16)
}
}
.foregroundColor(.white)
.padding(20)
}
)
}
}

How to soften edges of a Rectangle SwiftUI

I'm currently running into a problem of "harsh" edges when I try to create a rounded rectangle using a gradient.
In this gradient you can see around the corners it gets especially dark, and I'm not sure how to fix this.
I'm guessing it's stemming from using an extension to create the gradient so that I can use it as the foreground color instead of the background, but I'm not sure what I would use instead to fix this problem.
var body: some View {
GeometryReader { geometry in
RoundedRectangle(cornerRadius: 20)
.gradientForeground(colors: [Color("MainColor1"), Color("MainColor2")])
.frame(width: geometry.size.width * 0.9, height: 100, alignment: .center)
.padding(.leading, geometry.size.width * 0.05)
}
}
}
extension View {
public func gradientForeground(colors: [Color]) -> some View {
self.overlay(LinearGradient(gradient: .init(colors: colors),
startPoint: .topLeading,
endPoint: .bottomTrailing))
.mask(self)
}
}
Since you are working on Shape because you used RoundedRectangle, the right and correct way of coloring is fill, your issue is not connected to View to make an extension but it is about Shape.
extension Shape {
public func gradientForeground(colors: [Color]) -> some View {
self.fill(LinearGradient(gradient: .init(colors: colors), startPoint: .topLeading, endPoint: .bottomTrailing))
}
}
Use case:
struct ContentView: View {
var body: some View {
RoundedRectangle(cornerRadius: 50)
.gradientForeground(colors: [Color.red, Color.yellow])
.frame(width: 300, height: 300, alignment: Alignment.center)
}
}

SwiftUI opacity gradient

I am looking to have my scroll view fade out near the edge. I have implemented a mask, which almost achieves what I want. However, the scrolling stops working and the mask blacks out the rectangles (which should instead have images).
I have seen another post that overlays the background colour overtop of the view to create something that looks like a fade out, but my background is a gradient so it wouldn't work.
var body: some View {
ZStack {
LinearGradient(
gradient: Gradient(colors: [Color(#colorLiteral(red: 0.1333333333, green: 0.7098039216, blue: 0.4509803922, alpha: 1)), Color(#colorLiteral(red: 0.1607843137, green: 0.6705882353, blue: 0.8862745098, alpha: 1))]),
startPoint: .top, endPoint: .bottom)
.ignoresSafeArea()
LinearGradient(gradient: Gradient(colors: [.clear, .black, .clear]), startPoint: .leading, endPoint: .trailing)
.mask(ScrollingRectangles())
}
}
Here is the result of the above code:
Below is an example I threw together to illustrate what I'm trying to achieve.
You can check out this: https://designcode.io/swiftui-handbook-mask-and-transparency
OR
You can use masking to implement the transparency effect
ZStack {
// Your View here....
}
.mask(LinearGradient(gradient: Gradient(colors: [.black, .black, .black, .clear]), startPoint: .bottom, endPoint: .top))