1

Here I got 2 shapes, one Rectangle and one Circle, which with action of a Button only one of them became visible to user, I tried to use @Namespace for this transform, but did not panned out!

MY Goal: Having a nice and smooth transform animation from one Shape to other.

enter image description here

struct ContentView: View { @State var action: Bool = false @Namespace var sameShape var body: some View { ZStack { Group { if action { Circle() .fill(Color.blue).frame(width: 150, height: 150, alignment: .center) .matchedGeometryEffect(id: "Dakota148Zero", in: sameShape) } else { Rectangle() .fill(Color.red).frame(width: 150, height: 150, alignment: .center) .matchedGeometryEffect(id: "Dakota148Zero", in: sameShape) } } .animation(.easeInOut) VStack { Spacer() Button("transform") { action.toggle() }.font(Font.largeTitle).padding() } } } } 
1

3 Answers 3

3

Here is way to do it by representing the circle and square as a RoundedRectangle with different cornerRadius values:

struct ContentView: View { @State var action = false var body: some View { ZStack { RoundedRectangle(cornerRadius: action ? 0 : 75) .fill(action ? Color.red : .blue) .frame(width: 150, height: 150, alignment: .center) .animation(.easeInOut) VStack { Spacer() Button("transform") { action.toggle() } .font(Font.largeTitle) .padding() } } } } 

demo in simulator

Sign up to request clarification or add additional context in comments.

3 Comments

thanks a lot, that was first thing I thought about it! LoL But I am looking for decent transform animation
With mine solution and this being here, I'm wondering what is a "decent transform animation" that these two solutions are not? @Omar
@IiroAlhonen, yes it gives the illusion of transform, but I can not use this cornerRadios to transform to an other shape like Star, the point of my question is the transform animation, not solving an example of it
2

Group is not real container, so don't store animation. Replace Group with some stack, like

 VStack { if action // ... other code no change 

2 Comments

Agreed. Replace Group with ZStack and it should work.
I already made the changes no success! even used withAnimation in Button, nothing
2

With iOS14 out, you can use matchedGeometryEffect(). If you are using iOS14, I would recommend this approach.

https://www.hackingwithswift.com/quick-start/swiftui/how-to-synchronize-animations-from-one-view-to-another-with-matchedgeometryeffect

https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:)

So in your solution, if you replace action.toggle() with withAnimation{self.action.toggle()} in your button code, it will animate.

Button("transform") { withAnimation{self.action.toggle()} } .font(Font.largeTitle).padding() 

This solution works on the simulator for me (Xcode 12.1, iPhone 11 iOS 14.1):

import SwiftUI struct ContentView: View { @State var action: Bool = false @Namespace var transition var body: some View { ZStack { Group { if action { Circle() .fill(Color.blue).frame(width: 150, height: 150, alignment: .center) .matchedGeometryEffect(id: "shape", in: transition) } else { Rectangle() .fill(Color.red).frame(width: 150, height: 150, alignment: .center) .matchedGeometryEffect(id: "shape", in: transition) } } .animation(.easeInOut) VStack { Spacer() Button("transform") { withAnimation{self.action.toggle()} }.font(Font.largeTitle).padding() } } } } 

The matchedGeometryEffect() doesn't want to animate different shapes (including cornerRadius) or colors that nicely, not sure if this is a bug that will get fixed in future patches or just a feature that needs to be worked around by regular animations. With me playing around with matchedGeometryEffect(), it seems to do great with sizing things up and down, like shown with this code:

import SwiftUI struct ContentView: View { @State private var animate: Bool = false @Namespace private var transition var body: some View { VStack { if animate { RoundedRectangle(cornerRadius: 75.0) .matchedGeometryEffect(id: "shape", in: transition) .frame(width: 250, height: 250, alignment: .center) .foregroundColor(Color.blue) .animation(.easeInOut) .onTapGesture { animate.toggle() } } else { // Circle RoundedRectangle(cornerRadius: 75.0) .matchedGeometryEffect(id: "shape", in: transition) .frame(width: 150, height: 150, alignment: .center) .foregroundColor(Color.red) .animation(.easeInOut) .onTapGesture { animate.toggle() } } } } } 

6 Comments

@Omar Pasted the entire code that works for me in the simulator without issues.
I had the same result before asking this question, look the code and animation of @vacawama he got the right effect but it is not transform animation or kind of that, he works with cornerRadius
@Omar now I got really interested, so will do some more research.
Yes! This Topic is very hard, I wanted build a custom animation, but it would working only and only for transform from Circle to Rectangle or from Rectangle to Circle! but what about other Shapes! like transform from a Rectangle to Pentagon or to a Star! I got an idea to work on, and it is working on path of shape, actually it is very hard and big project, I believe it would be better working with Metal or SpritKit for a general Animation usage. But for sure the way to go maybe is path and core Graphic
Definitely, this question could be a reason to jump on pool of Metal and see what is going there as well.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.