Skip to content

Instantly share code, notes, and snippets.

@mattyoung
Last active December 29, 2022 22:26
Show Gist options
  • Save mattyoung/873e9495573ef7a89a6f99dc3875d855 to your computer and use it in GitHub Desktop.
Save mattyoung/873e9495573ef7a89a6f99dc3875d855 to your computer and use it in GitHub Desktop.
import SwiftUI
// VVVVVv
// the same math is used everywhere
enum Elliptical {
/// Calculate the cartitian coordinate (x, y)
/// - Parameters:
/// - angle: at this angle
/// - bounds: ellipse bounds
/// - Returns: the coordinate in a tuple
static func coordinate(angle: Angle, bounds: CGSize) -> (x: Double, y: Double) {
(x: bounds.width / 2 + bounds.width / 2 * cos(angle.radians), y: bounds.height / 2 + bounds.height / 2 * sin(angle.radians))
}
}
struct EllipticalOrbit: View {
@State private var viewSize = CGSize.zero
@State private var rotation = Angle.zero
let duration = 2.0
var body: some View {
ZStack {
Ellipse()
.foregroundColor(.gray)
// this cyan color dot move around a circle works
Circle()
.foregroundColor(.cyan)
.frame(width: 50, height: 50)
.overlay {
Text("Circular Orbit")
.fixedSize()
.rotationEffect(-rotation)
}
.offset(x: 150, y: 150)
.rotationEffect(rotation)
.animation(Animation.linear(duration: duration).repeatForever(autoreverses: false), value: rotation)
// VVVVVv
// this dot should move along elliptical orbit but is not
// Why is this not moving on the elliptical orbit?
let (x, y) = Elliptical.coordinate(angle: rotation, bounds: viewSize)
Circle()
.foregroundColor(.yellow)
.frame(width: 50, height: 50)
.overlay {
Text("Elliptical Orbit")
.fixedSize()
.rotationEffect(-rotation)
}
.offset(x: x, y: y)
.rotationEffect(rotation)
.animation(Animation.linear(duration: duration).repeatForever(autoreverses: true), value: rotation)
}
.onAppear {
self.rotation = Angle.degrees(360)
}
.readSize($into: $viewSize)
}
}
struct EllipseShapeMy: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
// Start at angle zero coordinate
path.move(to: CGPoint(x: rect.width, y: rect.height / 2))
for degree in stride(from: 0.0, through: 360.0, by: 5.0) {
// VVVVVv
// use the same calculation and this shape look right on screen
let (x, y) = Elliptical.coordinate(angle: Angle(degrees: degree), bounds: rect.size)
path.addLine(to: CGPoint(x: x, y: y))
}
return path
}
}
struct EllipticalOrbitAndShape: View {
var body: some View {
VStack {
EllipticalOrbit()
.frame(height: 200)
.border(.yellow)
.overlay {
EllipseShapeMy()
.stroke(Color.green, lineWidth: 4)
.border(.pink)
}
}
}
}
struct EllipticalOrbitAndShape_Previews: PreviewProvider {
static var previews: some View {
EllipticalOrbitAndShape()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment