Home > Software design >  SwiftUI question about animations what is happening here?
SwiftUI question about animations what is happening here?

Time:07-20

import SwiftUI

struct ContentView: View {

    let letters = Array("Testing stuff")
    @State private var enabled = false
    @State private var dragAmount = CGSize.zero


    var body: some View {
        HStack(spacing: 0)
        {
            ForEach(0..<letters.count) { num in
                Text(String(letters[num]))
                    .padding(5)
                    .font(.title)
                    .background(enabled ? .blue : .red)
                    .offset(dragAmount)
                    .clipShape(Circle())
                    .animation(.default.delay(Double(num) / 20), value: dragAmount)
            }

        }
        .gesture(
            DragGesture()
                .onChanged { dragAmount = $0.translation}
                .onEnded { _ in
                    dragAmount = .zero
                    enabled.toggle()
                }
        )




    }
}

So I have this piece of code, I'm mostly just testing out animation stuff, originally the clipShape modifier was before the offset modifier and everything worked and went as expected, but when I move the clipShape modifier to be after the offset everything still animates but it seems like it's stuck in the Shape and I can't see anything outside the Circle. Could someone maybe explain exactly why this is?

I understand the order of the modifiers is obviously very important in SwiftUI but to me it seems like whenever dragAmount changes then each view gets redrawn and offset and that offset modifier just notices changes in dragAmount and when it notices one it just offsets but why is it a problem if I put clipShape after that? Shouldn't it still totally be fine? I obviously don't understand why the order of the modifiers is important in this case so it would be nice if someone could clarify.

CodePudding user response:

It doesn't work because the text is offsetted, and then clipShape clips the original location for the text.

Paul Hudson sums it up well:

Using offset() will cause a view to be moved relative to its natural position, but won’t affect the position of other views or any other modifiers placed after the offset.

- Diagram

If you want the content to be clipped, then offsetted, use the clipShape modifier before the offset modifier.

Then it should look something like this (the part you can see is outlined in red):

Diagram 2

  • Related