Home > front end >  How can a child view be contained within the borders of its parent view in SwiftUI?
How can a child view be contained within the borders of its parent view in SwiftUI?

Time:07-08

I am trying to plot y-values against x-values, which are 0, 1, .., y.count-1. Users can choose to zoom in or out by specifying different ymin and ymax values. Here is the simplified code:

import SwiftUI

struct LineGraph: Shape {
    let y: [Double]
    let ymin: Double
    let ymax: Double
    
    func path(in rect: CGRect) -> Path {
        // for simplicity x-axis has values 0, 1, .., y.count-1
        let dx =  rect.width / CGFloat(y.count-1)

        // ycur is the current y point.
        let yrange = ymax - ymin
        let dy = rect.height / yrange
        let ycur = dy * (y[0]-ymin)
        
        var path = Path()
        path.move(to: CGPoint(x: 0, y: rect.height - ycur))
        for k in 1..<y.count {
            path.addLine(to: CGPoint(x: dx * CGFloat(k),
                                     y: rect.height - dy * (y[k]-ymin)))
        }
        
        return path
    }
}


struct ContentView: View {
    var body: some View {
        VStack {
            LineGraph(y: [8.0, 5.0, -2.0, -2.0, 3.0, 1.0],
                      ymin: -2.0,
                      ymax: 8.0)
            .stroke(.black)
        }
        .frame(width: 200, height: 300)
        .border(.red, width: 3)
            
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Initiating the LineGraph with the y's min and max values, which are -2 and 8, yields an expected result. However, if I initiate it with ymin:0 and ymax: 5, then I get the right side plot below:

enter image description here

My question is how can the child view LineGraph be contained within the border of its parent view VStack (within the red frame)? I tried .mask() with a clear rectangle and also overlaying this graph on a rectangle but couldn't get the result that I wanted. One solution is to find intersection points of the graph with the lines y=ymax and y=ymin, but I wonder if there is another way such as masking.

CodePudding user response:

I assume you wanted clipping, like

    VStack {
        LineGraph(y: [8.0, 5.0, -2.0, -2.0, 3.0, 1.0],
                  ymin: -2.0,
                  ymax: 8.0)
        .stroke(.black)
    }
    .frame(width: 200, height: 300)
    .border(.red, width: 3)
    .clipped()                 // << here !!
        
  • Related