Search code examples
swiftswiftuipositionviewmodifier

SwiftUI .position modifier with coordinates


I want to place items on an image with the modifier .position using the coordinates of each item. But when I look at the rendering, I don't understand the logic of the position of the items , what formula is used to place the items on the image and what frame of reference is being used. My code:

ZStack {
    Image(self.schema.image)
        .resizable()
        .aspectRatio(contentMode: .fill)
        .border(Color.white)
        .shadow(color: self.colorShadow ? Color.green : Color.gray.opacity(0.5) ,radius: 10)
        .overlay(
            ForEach(self.schema.item) { item in
                Text(String(item.id))
                    .font(.headline)
                    .foregroundColor(Color.black)
                    .padding(5)
                    .overlay(
                        Circle().stroke(Color.black, lineWidth: 1)
                    )
                    .offset(x: 20, y: 100)
                    .position(x: CGFloat(item.coordinatesX), y: CGFloat(item.coordinatesY))
            }
    )
}

My coordinates:

Items(id: 1, name: "1", coordinatesX: 0, coordinatesY: 50),
Items(id: 2, name: "2", coordinatesX: 10, coordinatesY: 50),
Items(id: 3, name: "3", coordinatesX: 20, coordinatesY: 50),
Items(id: 4, name: "4", coordinatesX: 30, coordinatesY: 50),
Items(id: 5, name: "5", coordinatesX: 40, coordinatesY: 50),
Items(id: 6, name: "6", coordinatesX: 50, coordinatesY: 50),
Items(id: 7, name: "7", coordinatesX: 60, coordinatesY: 50),
Items(id: 8, name: "8", coordinatesX: 70, coordinatesY: 50)

The final result:

enter image description here

I don't understand why it's a diagonal. Thank you for your help!


Solution

  • You need container in overlay, like

    .overlay(ZStack {
        ForEach(self.schema.item) { item in
            Text(String(item.id))
                .font(.headline)
                .foregroundColor(Color.black)
                .padding(5)
                .overlay(
                    Circle().stroke(Color.black, lineWidth: 1)
                )
                .offset(x: 20, y: 100)
                .position(x: CGFloat(item.coordinatesX), y: CGFloat(item.coordinatesY))
        }
    })