Created
August 22, 2023 23:40
-
-
Save DevonMartin/e235ccd6d146c179ebab568253648020 to your computer and use it in GitHub Desktop.
Drag me!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct ContentView: View { | |
var body: some View { | |
NodeRenderer(views: [ | |
Node { | |
Text("Drag me!") | |
} | |
]) | |
} | |
} | |
@Observable | |
class NodeState { | |
var pos: CGPoint | |
init(pos: CGPoint) { | |
self.pos = pos | |
} | |
} | |
protocol NodeObject: View { | |
var state: NodeState { get set } | |
} | |
struct Node<Content: View>: NodeObject { | |
@State var state = NodeState(pos: CGPoint(x: 100, y: 100)) | |
@State var previousDrag: CGSize = .zero | |
@State var content: () -> Content | |
var drag: some Gesture { | |
DragGesture(coordinateSpace: .global) | |
.onChanged(updatePOS) | |
.onEnded(resetPOS) | |
} | |
var body: some View { | |
content() | |
.gesture(drag) | |
} | |
func updatePOS(value: DragGesture.Value) { | |
state.pos = CGPoint( | |
x: state.pos.x + value.translation.width - self.previousDrag.width, | |
y: state.pos.y + value.translation.height - self.previousDrag.height | |
) | |
self.previousDrag = value.translation | |
} | |
func resetPOS(_ ignored: DragGesture.Value) { | |
self.previousDrag = .zero | |
} | |
} | |
struct NodeRenderer: View { | |
@State var views: [any NodeObject] | |
var body: some View { | |
ForEach(Array(zip(views.indices, views)), id: \.0) { _, nodeObject in | |
AnyView(nodeObject) | |
.position(nodeObject.state.pos) | |
} | |
} | |
} | |
#Preview("Nodes") { | |
ContentView() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment