Transition zoom at Text in Swiftui when a previous fade in transition ends for the same Text

158 views Asked by At

I have two texts in a SwiftUI View and two @State wrappers. When the view appears the first text is visible and the second is not. After a few seconds the first text fadeouts and the second text should fade in at the same time. So far so good. Now here is my issue... after the second text fades in, a few seconds later the same second text named Text("HELLO FROM THE OTHER SIDE") has to zoom out. This is the issue i have. How should i change the code so i can trigger the zoom out transition called TextZoomOutTransition as well? Here is the code:

import SwiftUI

struct Transitions: View {
   
@State changeText: Bool
@State zoomText: Bool

    private var TextFadeOut: AnyTransition {
        .opacity
        .animation(
            .easeOut(duration: 0.3)
        )
    }
    
    private var TextFadeIn: AnyTransition {
        .opacity
        .animation(
            .easeIn(duration: 0.3)
        )
    }
    
    private var TextZoomOutTransition: AnyTransition {
        return .asymmetric(
            insertion: .opacity,
            removal: .scale(
                scale: 1000, anchor: UnitPoint(x: 0.50, y: 0.45))
            .animation(
                .easeInOut(duration: 2.0)
                .delay(0.1)
            )
        )
    }
    
    public var body: some View {
        
        ZStack(alignment: .center) {
            Color.clear
         
            
            VStack(spacing: 24) {
                
                if !changeText  {
                    Text("HELLO THERE")
                        .transition(TextFadeOut)
                } else if !zoomText {
                    Text("HELLO FROM THE OTHER SIDE")
                        .transition(TextFadeIn)
                }
            }
}
 .onAppear {
            zoomText = false
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                changeText = true
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
                zoomText = true
            }
        }
}
}
1

There are 1 answers

0
HunterLion On

The zoom out transition already does the fade in during insertion, you just need to add the duration. The same transition fades in at insertion and zooms out at removal.

Here's the code - I corrected some mistakes, if you don't mind (variables start with lower case, @State are variables...):

@State private var changeText = false
@State private var zoomText = false

private var textFadeOut: AnyTransition {
    .opacity
    .animation(
        .easeOut(duration: 0.3)
    )
}

private var textZoomOutTransition: AnyTransition {
    return .asymmetric(
        insertion: .opacity
        
        // Here: add duration for fade in
            .animation(
                .easeIn(duration: 0.3)
            ),
        
        removal: .scale(
            scale: 1000, anchor: UnitPoint(x: 0.50, y: 0.45))
        .animation(
            .easeInOut(duration: 2.0)
            .delay(0.1)
        )
    )
}

public var body: some View {
    
    ZStack(alignment: .center) {
        Color.clear
        
        
        VStack(spacing: 24) {
            
            if !changeText  {
                Text("HELLO THERE")
                    .transition(textFadeOut)
            } else if !zoomText {
                Text("HELLO FROM THE OTHER SIDE")
                
                // Use this transition for insertion and removal
                    .transition(textZoomOutTransition)
            }
        }
    }
    .onAppear {
        zoomText = false
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            changeText = true
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
            zoomText = true
        }
    }
}