Having rectangle with gradient fill and trying to animate color change.
...
Rectangle()
.fill(LinearGradient(
gradient: .init(stops: [Gradient.Stop(color: myColor, location: 0.0), Gradient.Stop(color: .blue, location: 1.0)]),
startPoint: .init(x: 0.5, y: startPoint),
endPoint: .init(x: 0.5, y: 1-startPoint)
))
.animation(Animation.easeIn(duration: 2))
...
While change of starting points is animated nicely; the color change is not animated at all and just "switches"
Any hints?
Select the Gradient Transform tool from the Tools panel. If you do not see the Gradient Transform tool in the Tools panel, click and hold on the Free Transform tool and then select the Gradient Transform tool from the menu that appears. Click an area filled with a gradient or bitmap fill.
Initializing Colors SwiftUI provides with multiple ways to initialize colors. One way to do it is using Color(red: ..., green: ..., blue: ...) . You can provide the RGB (Red, Green, blue) value on a 0-1 range. You can also initialize color with UIColor (from UIKit) and NSColor (from AppKit).
Thanks to the new @property defined in the CSS Properties and Values API Level 1 specification we can now have transition with custom properties (aka CSS variables).
SwiftUI has built-in support for animations with its animation() modifier. To use this modifier, place it after any other modifiers for your views, tell it what kind of animation you want, and also make sure you attach it to a particular value so the animation triggers only when that specific value changes.
So if anyone will be struggling with that my current solution is having two gradients in ZStack and animating opacity of the top one
Example gif
Here is rough example, the code sure can be written more nicely:
///helper extension to get some random Color
extension Color {
static func random()->Color {
let r = Double.random(in: 0 ... 1)
let g = Double.random(in: 0 ... 1)
let b = Double.random(in: 0 ... 1)
return Color(red: r, green: g, blue: b)
}
}
struct AnimatableGradientView: View {
@State private var gradientA: [Color] = [.white, .red]
@State private var gradientB: [Color] = [.white, .blue]
@State private var firstPlane: Bool = true
func setGradient(gradient: [Color]) {
if firstPlane {
gradientB = gradient
}
else {
gradientA = gradient
}
firstPlane = !firstPlane
}
var body: some View {
ZStack {
Rectangle()
.fill(LinearGradient(gradient: Gradient(colors: self.gradientA), startPoint: UnitPoint(x: 0, y: 0), endPoint: UnitPoint(x: 1, y: 1)))
Rectangle()
.fill(LinearGradient(gradient: Gradient(colors: self.gradientB), startPoint: UnitPoint(x: 0, y: 0), endPoint: UnitPoint(x: 1, y: 1)))
.opacity(self.firstPlane ? 0 : 1)
///this button just demonstrates the solution
Button(action:{
withAnimation(.spring()) {
self.setGradient(gradient: [Color.random(), Color.random()])
}
})
{
Text("Change gradient")
}
}
}
}
Update: *In the end I have explored several ways of animating gradient fills and summarized them here: https://izakpavel.github.io/development/2019/09/30/animating-gradients-swiftui.html *
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With