如何在 SwiftUI 的椭圆路径中移动对象?

How to move an object in Ellipse path in SwiftUI?

椭圆路径

我正在尝试移动椭圆路径中的对象。 但我不知道正确的方法,我认为它需要一些我直到现在才知道的数学和方程式

image of output

import SwiftUI

struct RotateObjectInEllipsePath: View {

let timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()

@State private var angle: Double = .zero
var body: some View {

    VStack {
        
        // circle shape
        Circle()
            .strokeBorder(Color.red, lineWidth: 2)
            .frame(width: 250, height: 250)
            .overlay(
            Image(systemName: "arrow.down")
                .offset(x: 250/2)
                .rotationEffect(.degrees(angle))
            )
            
        
        //Spacer
        Spacer()
            .frame(height: 100)
        
        
        // ellipse shape
        Ellipse()
            .strokeBorder(Color.red, lineWidth: 2)
            .frame(width: 250, height: 150)
            .overlay(
                Image(systemName: "arrow.down")
                    .offset(x: 250/2)
                    .rotationEffect(.degrees(angle))
            )
            
         
    }// VStack
    .animation(.default)
    .onReceive(timer) { _ in
        angle += 1
    }
          
}

struct RotateObjectInEllipsePath_Previews: PreviewProvider {
static var previews: some View {
    RotateObjectInEllipsePath()
}}

我在社区中找到了这段代码

x = x_center + Acos(2pi*t/T);

y = y_center + Bsin(2pi*t/T);

当A == B时,轨迹为圆周

只改变.rotationEffect和.offset的顺序,offset可以同步椭圆轨迹也可以同步圆周轨迹

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct RotateObjectInEllipsePath: View {
    
    let timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
    
    let a: CGFloat = 250.0
    let b: CGFloat = 150.0
    
    @State private var angle: Double = .zero
    
    @State private var ellipseX: CGFloat = .zero
    @State private var ellipseY: CGFloat = .zero
    
    var body: some View {
        VStack {
            Circle()
                .strokeBorder(Color.red, lineWidth: 2)
                .frame(width: a, height: a)
                .overlay(
                    Image(systemName: "arrow.down")
                        .offset(x: a/2)
                        .rotationEffect(.degrees(angle))
                )
                
            Spacer()
                .frame(height: 60)
            
            Ellipse()
                .strokeBorder(Color.red, lineWidth: 2)
                .frame(width: a, height: b)
                .overlay(
                    Image(systemName: "arrow.down")
                        .rotationEffect(.degrees(angle))
                        .offset(x: ellipseX, y: ellipseY)
                )
            
            Spacer()
                .frame(height: 40)
        }// VStack
        .animation(.default)
        .onReceive(timer) { _ in
            angle += 1
            let theta = CGFloat(.pi * angle / 180)
            ellipseX = a / 2 * cos(theta)
            ellipseY = b / 2 * sin(theta)
        }
    }
    
}

struct RotateObjectInEllipsePath_Previews: PreviewProvider {
    static var previews: some View {
        RotateObjectInEllipsePath()
    }
}