Curious Jorge
Curious Jorge

Reputation: 1445

How to explicitly specify the series for plotted data-points in Swift Charts without using .XXX(by:) API?

I'm Curious, is there a way to specify the Series that Swift Chart data belongs to, if you can't use API like .symbol(by:) and foregroundStyle(by:) (ie any of the ones listed in Apple Docs under the heading "Encoding data into mark characteristics").

The situation I have is that I'm overriding symbol and foregroundStyle in my chart, so I can't use the above options that give automatic symbol and style, but also specify the series for the data. So I'm looking for another function that will directly indicate to Swift Charts what the series is, rather than doing that as a side-effect of some other action.

Here's some code to show the problem (for simplicity I've omitted symbols):

import Charts

struct ExplicitSeries: View {
    func chartPoint(x: Double, y: Double, series: Int) -> some ChartContent {
        LineMark(
            x: .value("Day", x),
            y: .value("Total", y)
        )
//        .foregroundStyle(by: .value("Count", "Series \(series)"))
        .foregroundStyle( series == 0 ? Color.blue : Color.green)
    }
    
    var body: some View {
        Chart {
            chartPoint(x: 0, y: 0, series: 0)
            chartPoint(x: 1, y: 1, series: 0)
            chartPoint(x: 0, y: 0.5, series: 1)
            chartPoint(x: 1, y: 0, series: 1)
        }
        .padding()
    }
}

And here's what the result looks like:

chart that doesn't know about series

Instead of two distinct series (one blue and one green), we have a single series of blue. Uncommenting the .foregroundStyle(by:) line will give the result I'm looking for (but without ability to override the colors):

enter image description here

Upvotes: 1

Views: 808

Answers (1)

Sweeper
Sweeper

Reputation: 273540

You can create your line marks with a series: parameter:

LineMark(
    x: .value("Day", x),
    y: .value("Total", y),
    series: .value("Series", series)
)
.foregroundStyle(series == 0 ? Color.red : Color.purple)

Now it will work.


Alternatively, you can use one of the chartForegroundStyleScale modifiers on the Chart, in addition to foregroundStyle(by:).

On the LineMark, do:

.foregroundStyle(by: .value("Series", series))

On the Chart, you can give it a dictionary representing the mapping of the possible values of series, to the colors you want:

.chartForegroundStyleScale([
    0: Color.red,
    1: Color.purple
])

It is also possible to pass a (some Plottable) -> some ShapeStyle function.

Upvotes: 3

Related Questions