0

I want to have a large Circle (A) start out in the middle (or near middle) of the screen. I then want to animate Circle A so that it will move along a path starting from the middle, along a curved path, up to the upper-left of the screen. As it is moving along the path, it should decrease in size down to its final dimensions.

The issue I'm running into is that I cannot get Circle A to move outside of its original bounds. Instead, it moves from the center, to 0, 0 for its subview; not the screen.

example of problem

import SwiftUI

struct ContentView: View {
    @State private var percentage: CGFloat = .zero
    @State private var scale: CGFloat = 1
    @State private var opacity: CGFloat = 1

    @State private var path = Path(.zero)

    @State private var startRect: CGRect = .zero
    @State private var endRect: CGRect = .zero

    var body: some View {
        ZStack(alignment: .top) {
            HStack {
                Circle()
                    .frame(width: 64, height: 64)
                    .padding()
                    .background {
                        GeometryReader { proxy in
                            Color.clear.onAppear {
                                endRect = proxy.frame(in: .local)
                            }
                        }
                    }

                Spacer()
            }
            .border(.red)

            ZStack {
                Circle()
                    .fill(.red)
                    .scaleEffect(scale)
                    .position(path.trimmedPath(from: 0,
                                               to: percentage).currentPoint ?? CGPoint(x: startRect.midX,
                                                                                       y: startRect.midY))
                    .animation(.easeInOut(duration: 2), value: percentage)
                    .frame(width: 256, height: 256)
                    .opacity(opacity)
                    .background {
                        GeometryReader { proxy in
                            Color.clear.onAppear {
                                startRect = proxy.frame(in: .local)
                            }
                        }
                    }
                    .border(.pink)

                Text("Hello, World")
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
        .frame(maxHeight: .infinity, alignment: .top)
        .background {
            Color.clear.onAppear {
                path.move(to: CGPoint(x: startRect.midX, y: startRect.midY))
                path.addQuadCurve(to: CGPoint(x: endRect.minX, y: endRect.minY), control: CGPoint(x: 300, y: 200))
            }
        }
        .onAppear {
            withAnimation(.easeInOut(duration: 2)) {
                percentage = 1
                scale = 0.25

                withAnimation(.linear.delay(2)) {
                    opacity = 0
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
dohpaz42
  • 520
  • 4
  • 18
  • 1
    You probably what to use a matchedGeometryEffect. See [this tutorial](https://swiftui-lab.com/matchedgeometryeffect-part1/) for an in depth explanation. – Yrb Jul 10 '23 at 13:01

0 Answers0