在 swiftUI 中动画渐变填充
Animating gradient fill in swiftUI
具有带渐变填充的矩形并尝试对颜色变化进行动画处理。
...
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))
...
虽然起点的变化动画效果很好;颜色变化根本没有动画,只是 "switches"
有什么提示吗?
因此,如果有人会为此苦苦挣扎,我目前的解决方案是 在 ZStack 中设置两个渐变并设置顶部渐变的动画不透明度
Example gif
这里是粗略的例子,代码当然可以写得更好:
///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")
}
}
}
}
更新: *最后我探索了几种动画渐变填充的方法并总结在这里:https://izakpavel.github.io/development/2019/09/30/animating-gradients-swiftui.html *
想再分享一个简单的选项。
两个带有动画纯色的矩形相互叠加。
顶部的 ZStack 使用渐变蒙版将它们混合在一起。
struct ContentView: View {
@State var switchColor = false
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 30)
.fill(switchColor ? Color.purple : Color.green)
ZStack {
RoundedRectangle(cornerRadius: 30)
.fill(switchColor ? Color.pink : Color.yellow)
}
.mask(LinearGradient(gradient: Gradient(colors: [.clear,.black]), startPoint: .top, endPoint: .bottom))
}
.padding()
.onTapGesture {
withAnimation(.spring()) {
switchColor.toggle()
}
}
}
}
具有带渐变填充的矩形并尝试对颜色变化进行动画处理。
...
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))
...
虽然起点的变化动画效果很好;颜色变化根本没有动画,只是 "switches"
有什么提示吗?
因此,如果有人会为此苦苦挣扎,我目前的解决方案是 在 ZStack 中设置两个渐变并设置顶部渐变的动画不透明度
Example gif
这里是粗略的例子,代码当然可以写得更好:
///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")
}
}
}
}
更新: *最后我探索了几种动画渐变填充的方法并总结在这里:https://izakpavel.github.io/development/2019/09/30/animating-gradients-swiftui.html *
想再分享一个简单的选项。
两个带有动画纯色的矩形相互叠加。 顶部的 ZStack 使用渐变蒙版将它们混合在一起。
struct ContentView: View {
@State var switchColor = false
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 30)
.fill(switchColor ? Color.purple : Color.green)
ZStack {
RoundedRectangle(cornerRadius: 30)
.fill(switchColor ? Color.pink : Color.yellow)
}
.mask(LinearGradient(gradient: Gradient(colors: [.clear,.black]), startPoint: .top, endPoint: .bottom))
}
.padding()
.onTapGesture {
withAnimation(.spring()) {
switchColor.toggle()
}
}
}
}