To preface, I am only a few weeks into SwiftUI. This project is also based on a hypocycloid. Having said that, I am trying to place a GeometryReader to track a very specific point (spoke point, or: the red dot) — which is offset, animated and nested inside of several ZStacks and an overlay — relative to the rest of the screen.
My issue is that, I don't know how to properly call the function to track the coordinates from within the GeometryReader and output it to a variable. I get the error that: Type '()' cannot conform to 'View' On top of that, my coordinates do not seem accurate, as I never get a negative value.
Without GeometryReader:
import SwiftUI
struct CreateHypotrochoid: View {
@State var isAnimating: Bool = true
@State var offsetX: CGFloat = .zero
@State var offsetY: CGFloat = .zero
var body: some View {
ZStack {
// MARK: - OUTER CIRCLE -
Circle()
.stroke(style: .init(
lineWidth: 2.0,
lineCap: .round,
lineJoin: .round))
.foregroundColor(Color.white)
.frame(width: 200,
height: 200)
ZStack {
// MARK: - INNER CIRCLE -
Circle()
.stroke(style: .init(
lineWidth: 2.0,
lineCap: .round,
lineJoin: .round))
.foregroundColor(Color.red)
.frame(width: 100,
height: 100)
.overlay(
// MARK: - INNER CIRCLE SPOKE -
Rectangle()
.stroke(style: .init(
lineWidth: 1.0,
lineCap: .round,
lineJoin: .round))
.foregroundColor(Color.white)
.frame(width: 1.0,
height: 100)
.offset(x: 0,
y: -50)
.rotationEffect(
Angle(degrees: isAnimating ? -360 : 0),
anchor: .center)
.animation(
Animation.linear(duration: 3)
.repeatForever(autoreverses: false), value: isAnimating)
)
.overlay(
// MARK: - DETERMINE SPOKE POINT -
// I need to track this circle's x & y coordinates.
// |
// V
Circle()
.foregroundColor(Color.red)
.frame(width: 6,
height: 6)
.offset(x: 0,
y: -100)
.rotationEffect(
Angle(degrees: isAnimating ? -360.0 : 0),
anchor: .center)
.animation(
Animation.linear(duration: 3)
.repeatForever(autoreverses: false), value: isAnimating)
)
// MARK: - INNER CIRCLE (CONTINUED) -
.offset(x: 0,
y: -50)
.rotationEffect(
Angle(degrees: isAnimating ? 360.0 : 0),
anchor: .center)
.animation(
Animation.linear(duration: 2)
.repeatForever(autoreverses: false), value: isAnimating)
}
}
.rotationEffect(Angle(degrees: 90))
.padding(20)
Button {
isAnimating.toggle()
} label: {
Text("Start/Stop")
}
}
}
And with GeometryReader:
import SwiftUI
struct CreateHypotrochoid: View {
@State var isAnimating: Bool = true
@State var offsetX: CGFloat = .zero
@State var offsetY: CGFloat = .zero
var body: some View {
ZStack {
// MARK: - OUTER CIRCLE -
Circle()
.stroke(style: .init(
lineWidth: 2.0,
lineCap: .round,
lineJoin: .round))
.foregroundColor(Color.white)
.frame(width: 200,
height: 200)
ZStack {
// MARK: - INNER CIRCLE -
Circle()
.stroke(style: .init(
lineWidth: 2.0,
lineCap: .round,
lineJoin: .round))
.foregroundColor(Color.red)
.frame(width: 100,
height: 100)
.overlay(
// MARK: - INNER CIRCLE SPOKE -
Rectangle()
.stroke(style: .init(
lineWidth: 1.0,
lineCap: .round,
lineJoin: .round))
.foregroundColor(Color.white)
.frame(width: 1.0,
height: 100)
.offset(x: 0,
y: -50)
.rotationEffect(
Angle(degrees: isAnimating ? -360 : 0),
anchor: .center)
.animation(
Animation.linear(duration: 3)
.repeatForever(autoreverses: false), value: isAnimating)
)
.overlay(
// MARK: - DETERMINE SPOKE POINT -
GeometryReader { geometry in
Circle()
.foregroundColor(Color.red)
.frame(width: 6,
height: 6)
.offset(x: 0,
y: 0)
.rotationEffect(
Angle(degrees: isAnimating ? -360.0 : 0),
anchor: .center)
.animation(
Animation.linear(duration: 3)
.repeatForever(autoreverses: false), value: isAnimating)
Text("coordinates: \(geometry.frame(in: .global).origin.dictionaryRepresentation)")
.offset(x: 50,
y: 50)
.frame(width: 200,
height: 200,
alignment: .center)
}
.background(Color.green)
.frame(width: 6,
height: 6)
.offset(x: 0,
y: -100)
.rotationEffect(
Angle(degrees: isAnimating ? -360.0 : 0),
anchor: .center)
.animation(
Animation.linear(duration: 3)
.repeatForever(autoreverses: false), value: isAnimating)
)
// MARK: - INNER CIRCLE (CONTINUED) -
.offset(x: 0,
y: -50)
.rotationEffect(
Angle(degrees: isAnimating ? 360.0 : 0),
anchor: .center)
.animation(
Animation.linear(duration: 2)
.repeatForever(autoreverses: false), value: isAnimating)
}
}
//.rotationEffect(Angle(degrees: 90))
.padding(20)
Button {
isAnimating.toggle()
} label: {
Text("Start/Stop")
}
}
}
CodePudding user response:
If you want to assign the changes of your GeometryReader
´s frame to a var use the .onChange(of:
modifier.
E.g:
.onChange(of: geometry.frame(in: .global)) { newValue in
test = newValue
}
with:
@State private var test: CGRect = .zero