swiftswiftuichartsswiftui-charts

LineMark chart display zero values for missing values in Swift Charts


Similar to a chart consisting of BarMark, I want my LineMark chart to drop to zero if there is no value for a point instead of simply connecting the existing values.

Example:

import Charts
import SwiftUI

struct ChartExample: View {
    let data: [(x: Int, y: Int)] = [(0, 1), (1, 3), (5, 1), (10, 1)]
    var body: some View {
        Chart {
            ForEach(data, id: \.x) { point in
                LineMark(x: .value("x", point.x), y: .value("y", point.y))
            }
        }.padding()
    }
}

#Preview {
    ChartExample()
}

Resulting LineMark chart:enter image description here Wanted LineMark chart:enter image description here

How can I achieve such behaviour? Do not expect that the entity (number, minute, hour, day…) or the span (1…10, 1 day, 3 months…) is always the same.

Are there any modifiers, or have these points somehow be added manually?


Solution

  • You do need to generate zero marks explicitly, because the SwiftUI charts have no idea for which X values the data is missing.

    As an example, in your case you do want to interpolate from x=0 to x=1, but not from x=0 to x=2; there is no way to express this logic in SwiftUI Charts.

    Code to fill the missing values might look like:

    let data: [(x: Int, y: Int)] = [(0, 1), (1, 3), (5, 1), (10, 1)]
    
    let filledData: [(x: Int, y: Int)] = data.reduce(into: []) { out, point in
        if let last = out.last {
            var xToFill = last.x+1
            while xToFill < point.x {
                out.append((xToFill, 0))
                xToFill += 1
            }
        }
        out.append(point)
            
    }