简体   繁体   English

在 SwiftUI 中使渐变视图动画颜色向一个方向旋转

[英]Make gradient view animation colors swirl in one direction in SwiftUI

So I have a linear gradient view and I have the colors animating with the .animation() modifier.所以我有一个线性渐变视图,我有.animation()修饰符的颜色动画。 Right now, the colors swirl back and forth as I adjust the start and end points of the gradient and use an .easeInAndOut() modifier to animate.现在,当我调整渐变的startend并使用.easeInAndOut()修饰符进行动画处理时,颜色会来回旋转。 I want the colors to swirl in one direction, clockwise, repeatedly, but instead it swirls back and forth.我希望颜色在一个方向上旋转,顺时针,重复,但它来回旋转。

struct AnimatedBackground: View {
   @State var start = UnitPoint.leading
   @State var end = UnitPoint.trailing
   
 
   
   let timer = Timer.publish(every: 1, on: .main, in: .default).autoconnect()
   let colors: [Color] = [ .blue, .red ]
   
   
   var body: some View {
       
       
       LinearGradient(gradient: Gradient(colors: colors), startPoint: start, endPoint: end)
           .animation(Animation.easeInOut(duration: 3).repeatForever())
           .onReceive(timer, perform: { _ in
               
              
   
                self.start = .topLeading
               self.end = .bottomTrailing
               
           
               self.start = .bottom
               self.end = .top
           
            
               self.start = .bottomLeading
               self.end = .topTrailing
               
               
               self.start = .leading
               self.end = .trailing
               
        
               self.start = .topLeading
               self.end =  .bottomTrailing
               
               
               self.start = .top
               self.end = .bottom
               
               
               self.start = .bottomLeading
               self.end = .topTrailing
               
            
               self.start = .leading
               self.end = .trailing
               
            
               
           }).edgesIgnoringSafeArea(.all)
   }
}

渐变颜色来回旋转。我希望颜色以顺时针方向旋转

The gradient colors swirl back and forth .渐变颜色来回旋转 I want the colors to swirl in one clockwise direction, smoothly and repeatedly.我希望颜色以顺时针方向旋转,平滑且重复。

Let's debug!让我们调试! First, before and after your huge sequence of self.start = ... , try adding print statements.首先,在大量self.start = ...之前和之后,尝试添加print语句。

print("Before: \(start), \(end)")
self.start = .topLeading
self.end = .bottomTrailing
self.start = .bottom
self.end = .top
self.start = .bottomLeading
self.end = .topTrailing
self.start = .leading
self.end = .trailing
self.start = .topLeading
self.end =  .bottomTrailing
self.start = .top
self.end = .bottom
self.start = .bottomLeading
self.end = .topTrailing
self.start = .leading
self.end = .trailing
print("After: \(start), \(end)")

You'll notice that both print s happen at pretty much the exact same time.您会注意到两个print几乎同时发生。

Before: UnitPoint(x: 0.0, y: 0.5), UnitPoint(x: 1.0, y: 0.5)之前:UnitPoint(x: 0.0, y: 0.5), UnitPoint(x: 1.0, y: 0.5)
After: UnitPoint(x: 0.0, y: 0.5), UnitPoint(x: 1.0, y: 0.5)之后:UnitPoint(x: 0.0, y: 0.5), UnitPoint(x: 1.0, y: 0.5)

This is because Swift code executes instantly, one line after another in an extremely small amount of time.这是因为 Swift 代码在极短的时间内一行接一行地立即执行。 As a result, start always becomes (x: 0.0, y: 0.5) ( .leading ), and end always becomes (x: 1.0, y: 0.5) ( .trailing ).结果, start总是变成(x: 0.0, y: 0.5) ( .leading ),而end总是变成(x: 1.0, y: 0.5) ( .trailing )。 Your gradient probably doesn't even animate at all!你的渐变可能根本没有动画!

To fix, you should simply get the current value of start and end , then manually calculate the next value.要修复,您应该简单地获取startend的当前值,然后手动计算下一个值。

struct AnimatedBackground: View {
    @State var start = UnitPoint.leading
    @State var end = UnitPoint.trailing

    let timer = Timer.publish(every: 1, on: .main, in: .default).autoconnect()
    let colors: [Color] = [.blue, .red]

    var body: some View {
        LinearGradient(gradient: Gradient(colors: colors), startPoint: start, endPoint: end)
            .animation(Animation.easeInOut(duration: 3).repeatForever(), value: start) /// don't forget the `value`!
            .onReceive(timer) { _ in
                
                self.start = nextPointFrom(self.start)
                self.end = nextPointFrom(self.end)

            }
            .edgesIgnoringSafeArea(.all)
    }
    
    /// cycle to the next point
    func nextPointFrom(_ currentPoint: UnitPoint) -> UnitPoint {
        switch currentPoint {
        case .top:
            return .topLeading
        case .topLeading:
            return .leading
        case .leading:
            return .bottomLeading
        case .bottomLeading:
            return .bottom
        case .bottom:
            return .bottomTrailing
        case .bottomTrailing:
            return .trailing
        case .trailing:
            return .topTrailing
        case .topTrailing:
            return .top
        default:
            print("Unknown point")
            return .top
        }
    }
}

Result:结果:

平滑的动画漩涡

Note: To get an even smoother animation, maybe check out rotationEffect .注意:要获得更流畅的动画,请查看rotationEffect

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM