swiftuiisometric

Combining of views using coordinates and zstack


i have an issue with ordering, combining and positioning of my solid shapes and text

the task is simple enough, but while im completely newbie in swfitui i cannot do it for my self

task: place solid shapes with zstack relative by their parrent using coordinates (including text of each shape) and apply isometric/perpective modifier

i will be glad for explanations and hints


this is what i have done for now

works without modifiers

and no with isometric modifier

struct ContentView: View {
  @ObservedObject var datas = ReadData()
  
  //MagnificationState
    
  //DragState

  //@GestureState
  //@State viewMagnificationState
  
  //@GestureState
  //@State viewDragState
  
  //magnificationScale
  
  //translationOffset
  
  //@State popoverState
  //@State selectedShape
  
  var body: some View {
    //magnificationGesture
    
    //dragGesture
    
    //magnificationGesture.simultaneously
    
    GeometryReader { geometry in
      ZStack(alignment: .topLeading) {
        MainShape(showingPopover: $popoverState,
                  setCurrentShape: $selectedShape,
                  alldatas: datas.pokedex)
      }          
      .scaleEffect(magnificationScale)
      .offset(translationOffset)
      //.position(x: geometry.size.width / 2, y: geometry.size.height / 2)
      //.gesture(both)
      //popover
    }
    .edgesIgnoringSafeArea(.all)
    .frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}

struct MainShape: View {    
  let alldatas: [PokedexElement]

  var body: some View {
    ForEach(alldatas, id: \.id) { shape in
      
      ZStack(alignment: .topLeading) {
        Text(shape.metaProperties.name)
          .font(.system(size: 20))
          .zIndex(2)
          .offset(x: shape.metaProperties.offset.x, y: shape.metaProperties.offset.y)

        Rectangle()
          .cornerRadius(shape.id == 1 ? 55 : 10)
          .foregroundColor(chooseColor(shape.metaProperties.color))
          .offset(x: shape.metaProperties.offset.x, y: shape.metaProperties.offset.y)
          .frame(
            width: shape.metaProperties.size.width,
            height: shape.metaProperties.size.height
          )
          .isometric()
          .zIndex(1)
          .onTapGesture {
            self.showingPopover = true
            self.setCurrentShape = shape.id
          }
      }
    }
  }
}

data:

[
    {
        "id": 1,
        "parentId": 0,
        "baseProperties": {
          "name": "",
          "descr": "",
          "contacts": ""
        },
        "metaProperties": {
            "name": "root",
            "status": true,
            "type": "plain",
            "size": {
                "width": 350,
                "height": 350
            },
            "offset": {
                "x": 0,
                "y": 0
            },
            "color": "blue"
        }
    },
    {
        "id": 2,
        "parentId": 1,
        "baseProperties": {
          "name": "object 1",
          "descr": "",
          "contacts": ""
        },
        "metaProperties": {
          "name": "child 1",
            "status": true,
            "type": "imobject",
            "size": {
                "width": 50,
                "height": 50
            },
            "offset": {
                "x": 50,
                "y": 50
            },
            "color": "red"
        }
    },
    {
        "id": 3,
        "parentId": 1,
        "baseProperties": {
          "name": "object 1",
          "descr": "",
          "contacts": ""
        },
        "metaProperties": {
          "name": "child 2",
            "status": true,
            "type": "imobject",
            "size": {
                "width": 100,
                "height": 50
            },
            "offset": {
                "x": 100,
                "y": 50
            },
            "color": "green"
        }
    }
]

and modifiers…

extension View {
  func chooseColor(_ name: String) -> Color {
    switch name {
    case "red":
      return Color.red
    case "blue":
      return Color.blue
    case "brown":
      return Color.brown
    case "green":
      return Color.green
    case "yellow":
      return Color.yellow
    case "white":
      return Color.white
    default :
      return Color.black
    }
  }
  
  func perspective() -> some View {
    self
      .rotation3DEffect(.degrees(45), axis: (x: 1, y: 0, z: 0))
  }
  
  func isometric() -> some View {
    self
      .rotationEffect(Angle.init(degrees: 45))
      .scaleEffect(y: 0.5)
  }
}

Solution

  • task was easy, instead of using regular solid shapes with "magic methods from black box" do it all manually

    convert decart to iso and place it whatever you want together with text or anything else and offset will be fine