0

I have a rectangle view that I animate the position when position state changes. This animates implicitly from original point to new state value.

@State var position: (Double, Double)

GeometryReader { geo in
  Rectangle()
      .fill(Color.red)
      .frame(width: 200, height: 200)
      .position(x: geo.size.width * CGFloat(position.0), y: geo.size.height * CGFloat(position.1))
}

How can I animate from specific position everytime position state changes. For example I would like to animate from (0.5, 0.5) instead of original position to new position state. This would make the view appear at position (0.5, 0.5) then animate to new position state.

This is the default animation

enter image description here

This is the animation I want to apply

enter image description here

Zack
  • 1,527
  • 2
  • 20
  • 32
  • can't you just change the position that you already have to the initial value that you want, then change it with the animation block ? do you have a gif of the expected result? `position = (1,1); withAnimation { position = (0.1,0.1) }` honestly it's seems a janky animation but i can see some uses. – Gry Aug 14 '21 at 03:48
  • @Gry I added some gif that shows the default and expected animation – Zack Aug 14 '21 at 17:17

1 Answers1

0

Here's an example of what i hope is what you needed, in the move function is where i added the start and end position change state logic.

i renamed and updated the position type because the 'position' name is already reserved by swiftui if you use it inside a View function. The var animate state is not needed most of the time, it's function is to disable the animation to move the rectangle on the desired animation offset but is just there in case you want to chain multiple change positions at the same time, otherwise you can remove it.

You can test changing the from and to values as you need.

struct ExampleView: View {
    @State var positionPoint: CGPoint = CGPoint.init(x: 0.5, y: 0.5)
    @State var animate: Bool = false

    var body: some View {
        ZStack {
            GeometryReader { geo in
                Rectangle()
                    .fill(Color.red)
                    .frame(width: 200, height: 200)
                    .position(x: geo.size.width * positionPoint.x,
                              y: geo.size.height * positionPoint.y)
                    .animation(animate ? .easeIn : nil)
            }
            
            VStack(spacing: 10) { // some test button
                Button(action: {
                    move(from: (0.2, 0.7), to: (0.8, 0.3))
                }, label: {
                    Text("from: (0.2, 0.7), to: (0.8, 0.3)")
                })
                Button(action: {
                    move(from: (1, 1), to: (0.1, 0.1))
                }, label: {
                    Text("from: (1, 1), to: (0.1, 0.1)")
                })
                Button(action: {
                    move(from: (0.6, 0.6), to: (0.5, 0.9))
                }, label: {
                    Text("from: (0.6, 0.6), to: (0.5, 0.9)")
                })
                Button(action: {
                    move(from: (0.8, 0.1), to: (0.3, 1))
                }, label: {
                    Text("from: (0.8, 0.1), to: (0.3, 1)")
                })
            }
        }
    }
    
    func move(from: (CGFloat, CGFloat), to: (CGFloat, CGFloat)) {
        animate = false
        positionPoint = CGPoint.init(x: from.0, y: from.1)
        withAnimation {
            animate = true
            positionPoint = CGPoint.init(x: to.0, y: to.1)
        }
    }

}
Gry
  • 101
  • 6
  • I tested the ExampleView but they move from the "from" point to "to" point. I want to animate from example (0.5, 0.5) to the "to" point. The view is already at a set position but I want it to jump to (0.5, 0.5) then animate from there – Zack Aug 14 '21 at 20:50
  • hmm if you want from 0.5,0.5 to the "to" point. you can set the move function like this. `move(from: (0.5, 0.5), to: (0.3, 1))`. and it will jump always from the middle. If its not what your searching sorry but i'm afraid i don't know at this point what you need. whenever i tap the 4 buttons in the exampleview they jump to the `from` position that are ( 0.2,0.7 - 1,1 - 0.6,0.6 - 0.8,0.1) – Gry Aug 14 '21 at 22:42