Como fazer com que algum ponto se torne arrastável através de um conjunto de arestas de visualização como no vídeo:
Em vez de arrasto livre:
Nem sei por onde começar, pois não consigo medir os limites de uma visualização sem o GeometryReader.
Entretanto, o GeometryReader não é adequado neste caso porque são visualizações diferentes em camadas separadas.
Exemplo de visualização:
struct ContentView: View {
@State var point: CGPoint = .zero
var body: some View {
ZStack {
//foreach Nodes
NodeView()
NodeView()
.offset(x:0, y:100)
//foreach Points
BezierPoint(p1: $point)
}
}
}
struct NodeView : View {
// var nodeViewModel: NodeViewModel
// with exact location in space
var body: some View {
Text("Business")
.multilineTextAlignment(.center)
.foregroundStyle(.red)
.shadow(color: .black, radius: 2 )
.frame(minHeight: 40)
.padding( EdgeInsets(horizontal: 20, vertical: 14) )
.background {
// ANY Shape can be here
RoundedRectangle(cornerRadius: 10)
}
}
}
struct BezierPoint: View {
@Binding var p1: CGPoint
let pointsSize: CGFloat = 15
var body: some View {
GeometryReader { reader in
ControlPointHandle(size: pointsSize)
.offset( CGSize(width: p1.x + reader.size.width/2, height: p1.y + reader.size.height/2) )
.gesture(
DragGesture()
.onChanged { value in
self.p1 = value.location.relativeToCenter(of: reader.size, minus: true)
}
)
}
}
}
private struct ControlPointHandle: View {
let size: CGFloat
var body: some View {
Circle()
.frame(width: size, height: size)
.overlay(
Circle()
.stroke(Color.blue, lineWidth: 2)
)
.offset(x: -size/2, y: -size/2)
}
}
fileprivate extension CGPoint {
func relativeToCenter(of size: CGSize, minus: Bool = false) -> CGPoint {
let a: CGFloat = minus ? -1 : 1
return CGPoint(x: x + a * size.width/2, y: y + a * size.height/2)
}
}