SwiftUI 与rotation3DEffect 动画冲突

Posted

技术标签:

【中文标题】SwiftUI 与rotation3DEffect 动画冲突【英文标题】:SwiftUI conflict with rotation3DEffect animation 【发布时间】:2020-11-05 02:39:39 【问题描述】:

代码参考:https://github.com/amosgyamfi/swiftui-animation-library/blob/master/After%20WWDC2020/Parallax%203D/ios_3d_parallax.gif

当我改变状态 Horizo​​ntalAlignment 并在 VStack(alignment: Horizo​​ntalAlignment) 中使用它时,内容将从左移到中心。

我想通过点击按钮在中心和前导之间切换

当前效果:

预期效果:

import SwiftUI
struct ContentView: View 
    
    @State private var rotateIn3D = false
    @State private var horizontalAlignment: HorizontalAlignment = .leading
    
    let weatherBg = LinearGradient(gradient: Gradient(colors: [Color.blue, Color.white]), startPoint: .topLeading, endPoint: .bottomTrailing)
    
    var body: some View 
        VStack
            ZStack  // Weather
                VStack(alignment: horizontalAlignment) 
                    Text("Wednesday")
                    
                    Text("18°")
                        .font(.system(size: 44))
                        .fontWeight(.thin)
                    
                    Spacer()
                    Image(systemName: "cloud.sun.fill")
                    Text("Partly Cloudy")
                        .frame(width: 150, height: 20, alignment: .leading)
                    Text("H:21° L:12°")
                    
                
                .padding()
                .background(Color.blue)
                .background(Color.yellow)
                .cornerRadius(22)
                .foregroundColor(.white)
                
            .frame(width: 170, height: 170, alignment: .leading)
            .rotation3DEffect(.degrees(rotateIn3D ? 12 : -12), axis: (x: rotateIn3D ? 90 : -45, y: rotateIn3D ? -45 : -90, z: 0))
            .animation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: true))
            .onAppear() 
                rotateIn3D.toggle()
            
            Button(action: 
                horizontalAlignment = .center
            , label: 
                Text("Change Horizontal Alignment to center")
            )
        
        
    


struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
            .preferredColorScheme(/*@START_MENU_TOKEN@*/.dark/*@END_MENU_TOKEN@*/)
    

【问题讨论】:

【参考方案1】:

只需根据每个状态的值制作动画即可。

使用 Xcode 12.1 / iOS 14.1 测试

  // ... other code

    .rotation3DEffect(.degrees(rotateIn3D ? 12 : -12), axis: (x: rotateIn3D ? 90 : -45, y: rotateIn3D ? -45 : -90, z: 0))
    .animation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: true), 
         value: rotateIn3D) // << here !!
    .animation(.default, value: horizontalAlignment)  // << here !!
    .onAppear() 
        rotateIn3D.toggle()
    

【讨论】:

@Asperi:对我来说没有 .animation(.default, value: Horizo​​ntalAlignment) 对我来说没有必要【参考方案2】:

这里:如你所愿

    import SwiftUI
struct ContentView: View 
    
    @State private var rotateIn3D = false

    var body: some View 
        VStack
            ZStack  
                VStack 
                    Text("Wednesday")
                    
                    Text("18°")
                        .font(.system(size: 44))
                        .fontWeight(.thin)
                    
                    Spacer()
                    Image(systemName: "cloud.sun.fill")
                    Text("Partly Cloudy")
                    Text("H:21° L:12°")
                    
                
                .frame(width: 150, height: 150)
                .padding()
                .background(Color.blue)
                .background(Color.yellow)
                .cornerRadius(22)
                .foregroundColor(.white)
                
            .frame(width: 170, height: 170, alignment: .leading)
            .rotation3DEffect(.degrees(rotateIn3D ? 12 : -12), axis: (x: rotateIn3D ? 90 : -45, y: rotateIn3D ? -45 : -90, z: 0))
            .animation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: true))
            .onAppear() 
                rotateIn3D.toggle()
            

        
        
    

更新:2.0.0 版

import SwiftUI
struct ContentView: View 
    
    @State var rotateIn3D = false
    @State var alignmentToggle = false
    
    
    let weatherBg = RadialGradient(gradient: Gradient(colors: [Color.blue, Color.white]), center: .center, startRadius: 30, endRadius: 200)
    
    var body: some View 
        
        
        
        ZStack
        
            
            
            VStack(alignment: alignmentToggle ? .leading : .center)
            
                
                
                Text("Wednesday")
                Text("18°").font(.system(size: 44)).fontWeight(.thin)
                Spacer()
                Image(systemName: "cloud.sun.fill")
                Text("Partly Cloudy")
                Text("H:21° L:12°")
                
            
            .padding()
            .frame(width: 170, height: 170)
            .background(weatherBg)
            .foregroundColor(.white)
            .cornerRadius(22)
            .shadow(color: Color.black.opacity(0.7), radius: 10, x: 0, y: 30)
            .rotation3DEffect(.degrees(rotateIn3D ? 12 : -12), axis: (x: rotateIn3D ? 90 : -45, y: rotateIn3D ? -45 : -90, z: 0))
            .animation( rotateIn3D ? Animation.easeInOut(duration: 2).repeatForever(autoreverses: true) : Animation.easeInOut(duration: 2))
            .onAppear()  rotateIn3D.toggle() 
            
            VStack
            
                Spacer()
                Button("alignment toggle")
                    rotateIn3D.toggle()
                    DispatchQueue.main.asyncAfter(deadline: .now() + 2.1) 
                        alignmentToggle.toggle()
                        DispatchQueue.main.asyncAfter(deadline: .now() + 2.1) 
                            rotateIn3D.toggle()
                        
                    
                
                .font(.title)
                .padding()
 
            
        
        
        
        
    

【讨论】:

当我更改状态 horizontalAlignment 并在 VStack(alignment: horizontalAlignment) 中使用它时,问题仍然存在 我要动态改变ui 我真的不懂你!你问中心,我给了答案!您想通过点击按钮在中心和前导之间切换吗?请说明你想要什么。 是的,我想通过点击按钮在中心和前导之间切换

以上是关于SwiftUI 与rotation3DEffect 动画冲突的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 动画并不总是运行

SwiftUI Tips 001:SwiftUI 概览

SwiftUI - 与 Microsoft 的 Firebase 身份验证

SwiftUI:将链接与 onTapGesture 一起使用

如何与代码并排打开 SwiftUI 预览? [复制]

如何将 UISearchController 与 SwiftUI 集成