0

我有一个视图,其中包含一个包含两个视图的 HStack。右视图包含一个图表。左视图包含图形 Y 轴的标签。我想将图表放在其父视图的中心。如果有人能指出我正确的方向来实现这一点,我将不胜感激。下面是我的代码。

问候,

克里斯

import SwiftUI
struct MainView: View {
    @EnvironmentObject var viewModel : ViewModel
    var body: some View {
        VStack (alignment: .center) {
            let maxYValue = viewModel.data.max { $0.Value < $1.Value }?.Value
            let minYValue = viewModel.data.max { $0.Value > $1.Value }?.Value
            let deltaY = maxYValue! - minYValue!
            let maxYVal = Int(round(maxYValue!))
            let minYVal = Int(round(minYValue!))
            HStack{
                VStack{
                    Text(String("\(maxYVal)"))
                    Spacer()
                    Text("2")
                    Spacer()
                    Text("3")
                    Spacer()
                    Text("3")
                    Spacer()
                    Text(String("\(minYVal)"))
                }.frame(width: 100, height: 510, alignment: .trailing)
                GeometryReader { geometry in
                    Path { path in
                        for index in viewModel.data.indices {
                            let xPosition = ((geometry.size.width) / (CGFloat(viewModel.data.count - 1))) * CGFloat(index + 0)
                            let yPosition =  (1 - (CGFloat(viewModel.data[index].Value - minYValue!)) / CGFloat(deltaY) ) * (geometry.size.height)
                            if index == 0 {
                                path.move(to: CGPoint(x : xPosition, y : yPosition))
                            }
                            path.addLine(to: CGPoint(x : xPosition, y: yPosition))
                        }
                    } .stroke(Color.blue, style: StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round))
                    Path { path in
                        path.move(to: CGPoint(x: 0, y: geometry.size.height))
                        path.addLine(to: CGPoint(x: 0, y: 0))
                        path.move(to: CGPoint(x: 0, y: geometry.size.height))
                        path.addLine(to: CGPoint(x: geometry.size.width, y: geometry.size.height))
                    }.stroke(Color.black, style: StrokeStyle(lineWidth: 2))
                    Path { path in
                        for index in 0...3 {
                            path.move(to: CGPoint(x: 0 , y: geometry.size.height * CGFloat(index) / 4))
                            path.addLine(to: CGPoint(x: geometry.size.width , y: geometry.size.height * CGFloat(index) / 4))
                        }
                    }.stroke(Color.gray, style: StrokeStyle(lineWidth: 0.5))
                } // end geometry reader
                .frame(width: 700, height: 500)// end inner geometry reader
            }
        } // end of vstack
    }
}
4

1 回答 1

0

感谢您的答复。发布查询后,我做了一些研究,得出的结论是我的代码太复杂了。所以,我重写了它,我认为它简化了。我创建了一个几何阅读器并使用它来创建两个组合起来占据整个父视图的矩形。在上部矩形中放置图表标题,在下部矩形中放置图表,并且正在将标签放在 X 和 Y 轴上。使用这种方法使我能够将项目准确地放置在矩形内,包括使图形居中。问题解决了。
我唯一需要弄清楚的是如何更改给定线条的笔划,而不必像我所做的那样创建多个路径。以下是更新后的代码。

再次感谢您的回复。

克里斯

import SwiftUI
struct MainView: View {
    var body: some View {
        GeometryReader { geometry in
            VStack (spacing: 0){
                let frameWidth = geometry.size.width
                let frameHeight = geometry.size.height
                Rectangle()
                    .fill(Color.clear)
//                    .border(Color.red)
                    .frame(width: frameWidth, height: frameHeight * 1/8 )
                    .overlay(
                        Text("Principal Values Over the Last Year")
                            .font(.largeTitle)
                    )
                Rectangle()
                    .fill(Color.clear)
                    .frame(width: frameWidth, height: frameHeight * 7/8 )
//                    .border(Color.black, width: 1)
                    .overlay(
                        PrincipalChart(frameWidth: frameWidth, frameHeight: frameHeight * 7/8)
                    )
                    .padding(0)
            } // end Vstack
        } // end geometry reader
    } // end body var
}  // end of MainView
struct PrincipalChart: View {
    let frameWidth : CGFloat
    let frameHeight : CGFloat
    @EnvironmentObject var viewModel : ViewModel
    var body: some View {
        ZStack {
            let maxYValue = viewModel.data.max { $0.Value < $1.Value }?.Value
            let minYValue = viewModel.data.max { $0.Value > $1.Value }?.Value
            let deltaY = maxYValue! - minYValue!
            let maxYVal = Int(round(maxYValue!))
            let minYVal = Int(round(minYValue!))
            let yAxisStep = Int((maxYVal - minYVal) / 4)
            Path { path in
                for index in viewModel.data.indices {
                    let xPosition = (frameWidth * 1/10) + ((frameWidth * 8/10) / (CGFloat(viewModel.data.count - 1))) * CGFloat(index + 0)
                    let yPosition =  (1 - (CGFloat(viewModel.data[index].Value - minYValue!)) / CGFloat(deltaY) ) * (frameHeight * 9/10)
                    if index == 0 {
                        path.move(to: CGPoint(x : xPosition, y : yPosition))
                    }
                    path.addLine(to: CGPoint(x : xPosition, y: yPosition))
                }
            } .stroke(Color.blue, style: StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round))
            Path { path in
                path.move(to: CGPoint(x: frameWidth * 1/10, y: 0))
                path.addLine(to: CGPoint(x: frameWidth * 1/10 , y: frameHeight * 9/10 ))
                path.addLine(to: CGPoint(x: frameWidth * 9/10, y: frameHeight * 9/10))
            }.stroke(Color.black, style: StrokeStyle(lineWidth: 2))
            Path { path in
                for index in 0...3 {
                    path.move(to: CGPoint(x: frameWidth * 1/10, y: (frameHeight * 9/10) * (CGFloat (index) / 4) ))
                    path.addLine(to: CGPoint(x: frameWidth * 9/10, y: (frameHeight * 9/10) * (CGFloat (index) / 4)))
                }
            }.stroke(Color.gray, style: StrokeStyle(lineWidth: 0.5))
            Text("\(maxYVal)").position(x: (frameWidth * 1/10) - 20, y: 1)
            let stepValue3 = maxYVal - yAxisStep
            Text("\(stepValue3)").position(x: (frameWidth * 1/10) - 20, y: -2 + (frameHeight * 9/10) * 1 / 4 )
            let stepValue2 = stepValue3 - yAxisStep
            Text("\(stepValue2)").position(x: (frameWidth * 1/10) - 20, y: -2 + (frameHeight * 9/10) * 2 / 4 )
            let stepValue1 = stepValue2 - yAxisStep
            Text("\(stepValue1)").position(x: (frameWidth * 1/10) - 20, y: -2 + (frameHeight * 9/10) * 3 / 4 )
            Text("\(minYVal)").position(x: (frameWidth * 1/10) - 20, y: -2 + (frameHeight * 9/10) * 4 / 4 )
        } // end z stack
    } // end body var
}  // end Principal Chart view
于 2021-09-21T21:13:21.657 回答