iosswiftswiftuiswiftui-charts

Swift chart issue: start and end y value connected for multiple line plots


I am trying to implement a stock chart with swift with two plots: one is the price and the other is a prediction/approximate for the price. I tried to implement this by using two loops of LineMark like below. For testing purpose, I used the same dataset with one's x value shifted up by 1. But I got the following issue where the start and end y values are connected when I add in a second loop of LineMark. How can I fix this?

VStack {
                 
            Chart {
                ForEach(self.entries, id: \.date) { entry in
                    LineMark(
                        x: .value("Date", entry.date),
                        y: .value("Price", entry.closePrice + 1)
                    ).foregroundStyle(.green)
                    
                }
                ForEach(self.entries, id: \.date) { entry in
                    LineMark(
                        x: .value("Date", entry.date),
                        y: .value("Price", entry.closePrice)
                    )
                    .foregroundStyle(.blue)
                    
                    
                    let curGradient = LinearGradient(
                        gradient: Gradient (
                            colors: [
                                .green.opacity(0.5),
                                .green.opacity(0.2),
                                .green.opacity(0.05),
                            ]
                        ),
                        startPoint: .top,
                        endPoint: .bottom
                    )
                    
                    AreaMark(
                        x: .value("Date", entry.date),
                        yStart: .value("Price", round(minY - ((maxY - minY) / 100) * 20)),
                        yEnd: .value("PriceEnd", entry.closePrice)
                    )
                    
                    .interpolationMethod(.cardinal)
                    .foregroundStyle(curGradient)
                    .alignsMarkStylesWithPlotArea()
                    
                }
                
            }
            .chartLegend(position: .top, alignment: .center)
            .chartYScale(domain: minY - ((maxY - minY) / 100) * 20...maxY + ((maxY - minY) / 100) * 20)
            .chartXAxis
            {
                AxisMarks(values: .stride(by: .day))
                { date in
                    AxisGridLine()
                    AxisValueLabel(format: .dateTime.weekday(.narrow), centered: true)
                }
            }.chartYAxis {
                AxisMarks(position: .leading)
            }
            
        }.frame(width: 347, height: 161.5)

Solution

  • It looks like you need to differentiate the data points being specified in the two ForEach loops better. Maybe, Swift Charts thinks they are the same series, right now. For instance, you could explicitly set the series in your call to LineMark using the (x:y:series:) initializer, or by using the .foregroundStyle(by:) modifier. Please see the "Plotting Multiple Lines" section of the LineMark docs for examples.

    Having said that, I see you are calling .foregroundStyle(:). I've not tried using that, in my Swift Charts travels, so I don't know if your result is expected. If you had provided a usable example, I could have verified. In future, please provide a minimal yet fully usable example in your questions. I would have dropped all the code about AreaMarks, Axes, etc from your code, and supplied some simple data so we could just copy and paste your code to reproduce the problem.