Post not yet marked as solved
Post marked as unsolved with 1 replies, 202 views
What works so far
In a game I am displaying a number to the user with some code like this:
Text("\(model.product)")
I want Text to have an interesting transition happen each time model.product changes. To arrange this I've used the id hack:
Text("\(model.product)")
.id(model.product)
// Transition here is included at the end of the post.
.transition(.explodeUp)
So now, in effect, each time the model.product changes, any existing Text showing the old product is removed (with a transition) and a new Text view is inserted to show the new product (with a transition).
So far, this works nicely, I've got my Transition all tweaked up, and it's a pretty nice effect [attached at the end]. Cool bananas!
What I want though
While this is nice as it is, not all model.product changes are alike…
The existing code uses the same transition regardless of how product.model has changed. What I want is for the transition used to depend on how product.model has changed.
FWIW, I actually want to vary the transition depending on why product.model has changed, but I can accomplish this in the model I think, so it seems unimportant to the SwiftUI side.
The current transition is great for when the number increases. I want to use something else if the number decreases (probably called AnyTransition.dropDown or something).
I'd like to be able to look at the old and new values of model.product and choose between two different transitions depending on whether the value has increased or decreased.
Looking at the Transition protocol, and Transaction, this seems like it probably ought to be possible to do this.
I think I'd certainly want to stop using the id hack. Instead perhaps I could have an extension on View which would read like this at the usage site…
Text(model.product)
.replacingWithTransitionOnChanges(of: model.product) { oldValue, newValue in
oldValue < newValue ? .explodeUp : .dropDown
}
And the extension declaration would perhaps look like this:
extension View {
func replacingWithTransitionOnChanges<Value: Hashable>(
of value: Value,
_ transitionSource: (Value, Value) -> some Transition
) {
// What in the name of fish cakes goes in here though? :-/
}
}
But as you see, I've got not a lot of an idea how I'd build the function. Yet?
Any ideas for that? Or else – perhaps there are really easy ways to get this effect that I'm not thinking of?
Thanks!
The .explodeUp transition
My transition declaration, if anyone is interested…
extension AnyTransition {
static var explodeUp: AnyTransition {
.asymmetric(
insertion: .scale(scale: 0.5)
.combined(with: .opacity)
.animation(.easeInOut(duration: 0.2)),
removal: .scale(scale: 1.8)
.combined(with: .opacity)
.combined(with: .rotate(angle: .degrees(Double.random(in: -20..<20))))
.animation(.easeInOut(duration: 0.4))
)
}
static func rotate(angle: Angle) -> AnyTransition {
.modifier(active: RotateModifier(angle: angle), identity: RotateModifier(angle: .zero))
}
}