简体   繁体   中英

SwiftUI Can't Make Multiple Line Path Work

I'm really struggling with the SwiftUI Path function. I'm attempting to have a single vertical line for temperature for each day of a year. The top point of the line to be the high temp for the day and the bottom point to be the low temp for the day.

I had even seen a Ray Wendelich example that was inspiration, but I simply cannot get it to work. https://www.raywenderlich.com/6398124-swiftui-tutorial-for-ios-creating-charts

After much frustration, I created this simple code to test (and to prove that the problem was not my decoded data).

struct ContentView: View {
    @State private var things365: [Thing] = []
    let myGradient = Gradient(colors: [
        Color(#colorLiteral(red: 0.5450980392, green: 0, blue: 0, alpha: 1)),
        Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)),
        Color(#colorLiteral(red: 0.1176470588, green: 0.5647058824, blue: 1, alpha: 1)),
        Color(#colorLiteral(red: 0, green: 0, blue: 0.5450980392, alpha: 1)),
        .yellow,
        Color(#colorLiteral(red: 1, green: 0.5490196078, blue: 0, alpha: 1)),
        Color(#colorLiteral(red: 0, green: 0.7647058824, blue: 1, alpha: 1)),
        Color(#colorLiteral(red: 0.5294117647, green: 0.8078431373, blue: 0.9803921569, alpha: 1)),
    ])

    var body: some View {
        ZStack {
            VStack(alignment: .leading) {
                Text("Show the Path")
                //put some other data here
                HStack  {
                    ForEach(things365, id: \.self) { t in
                        Path { p in
                            p.move(to: CGPoint(x: t.inc, y: CGFloat((t.maxt as NSString).doubleValue)))
                            p.addLine(to: CGPoint(x:t.inc, y: CGFloat((t.mint as NSString).doubleValue) + 500))
                        }
                        .stroke(LinearGradient(gradient: self.myGradient, startPoint: UnitPoint(x: 0.0, y: 1.0), endPoint: UnitPoint(x: 0.0, y: 0.0)))
                    }
                    .frame(width: 1)
                }
            }
        }
        .frame(width: 365, height: 600)
        .onAppear {
            self.makeThings()
        }
    }

    //simulate a years worth of temperature data
    func makeThings() {
        for x in 1...365 {
            let t = Thing(maxt: String(Int.random(in: 70..<110)), mint: String(Int.random(in: 0..<40)), inc: CGFloat(x))
            self.things365.append(t)
        }
    }
}

struct Thing: Hashable {
    let id = UUID()
    var maxt: String
    var mint: String
    var inc: CGFloat
}

This is what I want:

在此处输入图片说明

This is what I get:

在此处输入图片说明

Any guidance would be appreciated. Xcode 11.6, iOS 13.6

I would propose the following alternate - make model more convenient and use Rectangle instead of Path, also some fixes (as we have inverted coordinates).

在此处输入图片说明

struct TestTempGraph: View {
    @State private var things365: [Thing] = []
    let myGradient = Gradient(colors: [
        Color(#colorLiteral(red: 0.5450980392, green: 0, blue: 0, alpha: 1)),
        Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)),
        Color(#colorLiteral(red: 0.1176470588, green: 0.5647058824, blue: 1, alpha: 1)),
        Color(#colorLiteral(red: 0, green: 0, blue: 0.5450980392, alpha: 1)),
        .yellow,
        Color(#colorLiteral(red: 1, green: 0.5490196078, blue: 0, alpha: 1)),
        Color(#colorLiteral(red: 0, green: 0.7647058824, blue: 1, alpha: 1)),
        Color(#colorLiteral(red: 0.5294117647, green: 0.8078431373, blue: 0.9803921569, alpha: 1)),
    ])

    let plotHeight = CGFloat(600)

    var body: some View {
        ZStack {
            VStack(alignment: .leading) {
                Text("Show the Path")
                //put some other data here
                HStack(spacing: 0)  {
                    ForEach(things365, id: \.self) { t in
                        Rectangle()
                            .stroke(LinearGradient(gradient: self.myGradient, startPoint: UnitPoint(x: 0.0, y: 0.0), endPoint: UnitPoint(x: 0.0, y: 1.0)))
                            .frame(width: 1, height: t.maxt - t.mint)
                            .position(y: plotHeight - t.mint - (t.maxt - t.mint) / 2.0)
                    }
                }
                .frame(width: 365, height: plotHeight)
            }
        }
        .onAppear {
            self.makeThings()
        }
    }

    //simulate a years worth of temperature data
    func makeThings() {
        for x in 1...365 {
            let t = Thing(maxt: CGFloat.random(in: 70..<110), mint: CGFloat.random(in: 0..<40), inc: CGFloat(x))
            self.things365.append(t)
        }
    }
}

struct Thing: Hashable {
    let id = UUID()
    var maxt: CGFloat
    var mint: CGFloat
    var inc: CGFloat
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM