I am trying to use purely SwiftUI to build a guitar you can tap to add notes. Using HStacks and VStacks of Views or elements results in performance issues (it has to draw 6 x 24 views often). So, I was going to try an approach using an image, determine where was tapped, and add an overlay at that location.
I am aware of one method using a drag gesture with minimum distance of 0, but I need the drag gesture to swipe between taps in a TabView.
struct GuitarStringView: View {
let guitarString = Array(repeating: GuitarFretView(), count: 24)
var body: some View {
HStack {
ForEach(0 ..< 24) { item in
guitarString[item]
}
}
.frame(maxHeight: 36, alignment: .center)
}
}
struct GuitarFretView: View {
@State var tapped = false
var body: some View {
ZStack {
Path { path in
path.move(to: CGPoint(x:0, y: 18))
path.addLine(to: CGPoint(x: 50, y: 18))
}
.stroke(lineWidth: 3)
.onTapGesture {
withAnimation {
tapped.toggle()
}
}
// appears when the string is tapped
Circle()
.fill(self.tapped ? Color.gray : Color.clear)
.frame(width: 30, height: 30)
.onTapGesture {
withAnimation {
tapped.toggle()
}
}
} // ZSTACK
}
}
The method I found on Stack Overflow forums for getting the position is below. It worked, but then I was blocked from using the swipe for moving between tabs.
.simultaneousGesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onEnded { print("X position \($0.location)") })
Thanks for any guidance!