TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

Sending x and y from gesture to struct (Please help!)

Forums > SwiftUI

I want to make an app showing a graph with multitouch. When you drag one node, an edge connecting it with another node should follow it. My problem is that I don't know how to save information about node position in the node struct from drag gesture. I appreciate all the tips and Merry Christmas to everyone :)

Main code:

import SwiftUI

struct ContentView: View {
    @State var nodes = Nodes()
    @State var matrix = Matrix()

  var body: some View {

      ZStack {
          ForEach(0..<matrix.arr.count) {x in
              ForEach(0..<matrix.arr[x].count){y in
                  if matrix.arr[x][y] == 1 {
                      makeLine(from: nodes.n_array[x], to: nodes.n_array[y])
                  }
              }
          }

          ForEach(nodes.n_array, id: \.id) {
              $0.drawShape()
                  .draggable()
              $0.label()
                  .draggable()
          }
      }
  }
}

Drag gesture:

import SwiftUI

extension View {
    func draggable() -> some View {
        self
            .modifier(DraggableModifier())
    }
}

struct DraggableModifier: ViewModifier {
    @State var previousTranslation: CGSize?
    @State public var offset: CGPoint = .zero

    func body(content: Content) -> some View {
        content
            .offset(x: offset.x, y: offset.y)
            .gesture(DragGesture().onChanged { value in
                if let translation = previousTranslation {
                    let delta = CGSize(width: value.translation.width - translation.width,
                                       height: value.translation.height - translation.height)
                    offset.x += delta.width
                    offset.y += delta.height
                    previousTranslation = value.translation
                }
                else {
                    previousTranslation = value.translation
                }
            }
            .onEnded { _ in
                previousTranslation = nil
            })
    }
}

Edge drawing function:

import Foundation
import SwiftUI

func makeLine(from: Node, to: Node) -> some View {
   return Path() { path in
        path.move(to: CGPoint(x: from.x, y: from.y))
        path.addLine(to: CGPoint(x: to.x, y: to.y))
    }
   .stroke(Color(red: 0.25, green: 0.25, blue: 0.25), lineWidth: 4)
}

Node structure:

import Foundation
import SwiftUI

struct Node: Decodable, Hashable {
    public let id: Int
    public var x: Double
    public var y: Double
    public let text: String
    public var red: Double
    public var green: Double
    public var blue: Double
    public var shape: Int
}

extension Node {
    func circle() -> some View {
        Circle().fill(Color(red: red, green: green, blue: blue)).frame(width: 64, height: 64, alignment: .center).position(x: x, y: y)
    }

    func square() -> some View {
        Rectangle().fill(Color(red: red, green: green, blue: blue)).frame(width: 64, height: 64, alignment: .center).position(x: x, y: y)
    }

    @ViewBuilder func drawShape() -> some View {
        switch shape{
        case 1: circle()
        case 2: square()
            default: Text("Failed")
        }
    }

    func label() -> some View {
        return Text(text)
            .font(.system(size: 30))
            .bold()
            .position(x: x, y: y)
            .foregroundColor(Color(red: 0.25, green: 0.25, blue: 0.25))
    }
}

Array of nodes:

import Foundation

class Nodes: ObservableObject {
   public var n_array: [Node]

    init() {
        let url = Bundle.main.url(forResource: "nodes", withExtension: "json")!
        let data = try! Data(contentsOf: url)
        n_array = try! JSONDecoder().decode([Node].self, from: data)
    }
}

Edge structure:

import Foundation

struct Edge: Decodable {
    public let n1: Int
    public let n2: Int
}

Array of edges:

import Foundation
import SwiftUI

class Edges {
    public let e_array: [Edge]

    init() {
        let url = Bundle.main.url(forResource: "edges", withExtension: "json")!
        let data = try! Data(contentsOf: url)
        e_array = try! JSONDecoder().decode([Edge].self, from: data)
    }
}

Matrix with conections:

import Foundation

class Matrix: ObservableObject {
    private let nodes = Nodes()
    private let edges = Edges()
    public var arr: [[Int]]

    init() {
        arr = Array(repeating: Array(repeating: 0, count: nodes.n_array.count), count: nodes.n_array.count)
        var x:Int, y: Int
        for i in 0...edges.e_array.count-1 {
            x = edges.e_array[i].n1
            y = edges.e_array[i].n2
            arr[x][y] = 1
        }
    }
}

3      

Hacking with Swift is sponsored by Blaze.

SPONSORED Still waiting on your CI build? Speed it up ~3x with Blaze - change one line, pay less, keep your existing GitHub workflows. First 25 HWS readers to use code HACKING at checkout get 50% off the first year. Try it now for free!

Reserve your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.