0

I want use a button to trigger an animation on the rectangle, but I have no idea how to call an animation from an object that's not the one the animation is being called on.

    var body: some View {

        GeometryReader { fullView in
            ScrollView() {
                
                
                VStack{
                    
                    Rectangle()
                        .foregroundColor(.white)
                        .frame(width: 150, height: 150)
                    
                    Button(action: {
                        print("Here")
                        //Trigger animation here
                    }){
                        Text("Button")
                    }
                    Spacer()
                    
                }
                
            }
            
        }
    }
}

This is the general code that I working with.

Big Papa
  • 77
  • 1
  • 7
  • What are you trying to animate for the rectangle? The foreground color? The frame dimensions? – George May 08 '21 at 15:00
  • I was going to try to scale up the rectangles' size\. – Big Papa May 08 '21 at 15:02
  • Does this answer your question https://stackoverflow.com/a/63536007/12299030? Actually search by "animation scaleEffect" key works - there are a lot examples. – Asperi May 08 '21 at 15:17

1 Answers1

0

You can just change the value of a @State variable in a withAnimation(_:_:) block.

Here is a simpler version, with two options:

  1. Scale and change layout
  2. Scale and not change layout

Code:

struct ContentView: View {
    @State private var scale: CGFloat = 1
    
    var body: some View {
        VStack {
            Rectangle()
                .frame(width: 150 * scale, height: 150 * scale)  // 1
//                .frame(width: 150, height: 150)  // 2
//                .scaleEffect(scale)  // 2
            
            Button("Button") {
                print("Here")
                //Trigger animation here
                
                withAnimation {
                    scale = 2.5 - scale
                }
            }
            
            Spacer()
        }
    }
}

The 2.5 came from 1 + TARGET_SCALE. 1 -> 1.5, 1.5 -> 1.

George
  • 25,988
  • 10
  • 79
  • 133
  • Is there any way to then wait for that action to finish and then call something else? like would "DispatchQueue.main.asyncAfter(deadline: .now())" work? – Big Papa May 08 '21 at 15:19
  • @Elijah Unfortunately not that I know of. However if you explicitly set the animation type, e.g. `withAnimation(.easeInOut(duration: 0.2)) { ... }`, you can do that `DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { ... }` (outside of the block). However, if the button is tapped whilst already animating, the code to execute after will be called multiple times. – George May 08 '21 at 15:23
  • Is there any way to scale a SF Symbol? I'm trying to just use font(.system(size: 30 * scale)) but it gets cut off while scaling, and .scaleEffect but it gets blurry. I realize I should have put this in the original question, sorry. – Big Papa May 08 '21 at 15:37
  • @Elijah Make sure to use the `resizable()` modifier on the Image so it does actually change size. – George May 08 '21 at 15:39