0

I have a simple SwiftUI macOS view that animates some text by altering the font size when tapped. It goes from a fixed value to another. The animation works perfectly, but I'd like to add an extra piece of interaction. In the view there's a hidden button linked to the spacebar. I'd like to print out the fontSize at the moment in time when the spacebar gets pressed. If I print directly the fontSize variable, I get the value at the end of the animation.

import SwiftUI

struct MeasureFontSizeView: View {
    
    @State private var fontSize = 50.0
    
    var body: some View {
        ZStack {
            Text("Hello!")
                .font(.custom("Georgia", size: fontSize))
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            
            Button {
                // print out the font size
                // at this stage of the animation
                print(fontSize)
            } label: {
                Text("")
            }
            .buttonStyle(.borderless)
            .keyboardShortcut(" ", modifiers: [])
        }
        
        .onTapGesture {
            withAnimation(.linear(duration: 3)) {
                fontSize = 200.0
            }
        }
    }
}

Any advice?

  • Look into Animatable – lorem ipsum Jul 18 '23 at 14:15
  • 1
    Do you mean https://developer.apple.com/documentation/realitykit/animatabledata? – Roberto Arista Jul 18 '23 at 14:18
  • https://developer.apple.com/documentation/swiftui/animatable – lorem ipsum Jul 18 '23 at 14:28
  • The problem is a bit more complex than you imagine. Essentially, when we use SwiftUI's animation, the OS figures out how to show the intermediate views in the animation, but the variable that you are using has already changed. If you create your own animatable, you can get the intermediate data out. See https://github.com/globulus/swiftui-pausable-animation – Yrb Jul 18 '23 at 14:40

1 Answers1

0

Here is a solution that uses the swiftui-animation-observer package by globulus

import SwiftUI
import SwiftUIAnimationObserver

struct MeasureFontSizeView: View {
    
    @State private var fontSize = 50.0
    @State private var fontSizeProgress = 0.0
    
    var body: some View {
        ZStack {
            Text("Hello!")
                .font(.custom("Georgia", size: fontSize))
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .animationObserver(for: fontSize) { progress in
                    fontSizeProgress = progress
                }
            Button {
                // print out the font size
                // at this stage of the animation
                print(fontSizeProgress)
            } label: {
                Text("")
            }
            .buttonStyle(.borderless)
            .keyboardShortcut(" ", modifiers: [])
        }
        
        .onTapGesture {
            withAnimation(.linear(duration: 3)) {
                fontSize = 200.0
            }
        }
    }
}