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.
If you want the content to be clipped, then offsetted, use the
clipShape
modifier before theoffset
modifier.Then it should look something like this (the part you can see is outlined in red):