Skip to content

Instantly share code, notes, and snippets.

@eivindml
Created Dec 11, 2019
Embed
What would you like to do?
import SwiftUI
struct WheelData {
let strokeWidth: CGFloat
let knobWidth: CGFloat
}
struct WheelView: View {
@State var position: CGSize?
@State var angle: CGFloat = 0
let wheel = WheelData(
strokeWidth: 40,
knobWidth: 40
)
var body: some View {
GeometryReader { geometry in
ZStack {
Circle()
.stroke(Color.secondary, lineWidth: self.wheel.strokeWidth)
Circle()
.trim(from: 0.0, to: self.angle)
.stroke(Color.blue, lineWidth: self.wheel.strokeWidth)
Circle()
.fill(Color.primary)
.frame(
width: self.wheel.knobWidth,
height: self.wheel.knobWidth
)
.shadow(radius: CGFloat(10.0))
.offset(
self.position ??
CGSize(
width: geometry.size.width/2 - self.wheel.knobWidth/2,
height: 0
)
)
.gesture(DragGesture()
.onChanged { value in
// Get center coordinate
let center = (geometry.size.width - self.wheel.strokeWidth) / 2
// Calculate the ∠ from center to current touch point
let radians = atan2(value.location.y/center, value.location.x/center)
// Convert from radians to degrees
let degrees = radians * (180 / .pi)
// Normalize degrees to go from 0 to 360
let normalizedDegrees = (degrees + 360).truncatingRemainder(dividingBy: 360)
// Calculate new position for knob using the angle and the fixed radius
// sin = oppsite/hypotenus
// cos = adjacent/hyptenus
let x = cos(radians) * center
let y = sin(radians) * center
self.position = CGSize(
width: x,
height: y
)
// Update global angle
self.angle = normalizedDegrees / 360
// TODO: Emit angle from here
})
}.frame(
width: geometry.size.width - self.wheel.strokeWidth,
height: geometry.size.width - self.wheel.strokeWidth
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment