Date:

Share:

Fill bar marks with gradient in Swift Charts

Related Articles

with the new Swift charts Framework It’s really easy to create basic charts to visualize data in our apps. The framework also provides a lot of customization options to make our charts stand out. In this post we are going to see how to build a bar chart to visualize the average daily temperature in Christchurch for each month of the year. We will also fill the stripe marks with a linear gradient to emphasize cold and warm temperatures. The important point is to make the gradient stretch from top to bottom of the entire plot area instead of filling each bar mark separately to achieve the desired effect. This is what our final graph will look like.

We’ll start by creating a basic bar chart to plot the following data. Temperatures are indicated in degrees Celsius.

let data = [
    (month: "January", temp: 17.1),
    (month: "February", temp: 17.0),
    (month: "March", temp: 14.9),
    (month: "April", temp: 12.2),
    (month: "May", temp: 9.6),
    (month: "June", temp: 6.9),
    (month: "July", temp: 6.3),
    (month: "August", temp: 7.6),
    (month: "September", temp: 9.5),
    (month: "October", temp: 11.2),
    (month: "November", temp: 13.5),
    (month: "December", temp: 15.7)
]

I use wires for months of the year and double the temperature for simplicity here. In a real application you should store the temperature values ​​using the measurement Type. You can find out how to plot type values Measurement In one of my previous posts using projector measurements for values ​​in Swift Charts.

Our basic chart will have the month of the year on the x-axis and the average temperature value on the y-axis. We will show the abbreviated month string in the chart but provide the full string to Voice Over users with accessibilityLabel() Change applies to everyone BarMark.

Chart {
    ForEach(data, id: .month) {
        BarMark(
            x: .value("Month", String($0.month.prefix(3))),
            y: .value("Temperature", $0.temp)
        )
        .accessibilityLabel("($0.month)")
    }
}

The result is already good enough even with this very simple code, but there is more we can do.

Screenshot of a bar chart showing average daily temperature for the month in Christchurch with the bar markers filled in the default blue color

We can customize the appearance of the chart by applying a specific foreground style. In this case we will add a linear gradient going from blue to red to better visualize the cold and hot temperatures.

Chart {
    ForEach(data, id: .month) {
        BarMark(
            x: .value("Month", String($0.month.prefix(3))),
            y: .value("Temperature", $0.temp)
        )
        .accessibilityLabel("($0.month)")
    }
    .foregroundStyle(
        .linearGradient(
            colors: [.blue, .red],
            startPoint: .bottom,
            endPoint: .top
        )
    )
}

If we examine the result now, it appears that by default the gradient is applied from the bottom to the top of each individual bar. This is not what we want, as it does not match the temperature values ​​correctly. The hottest temperatures throughout the year have more of a red tint than colder temperatures.

A screenshot of a bar chart showing the average daily temperature for the month in Christchurch with the bar marks filled with a linear gradient from blue to red that starts and ends at the boundaries of each mark

To fix this we can apply the alignsMarkStylesWithPlotArea() changes the style. This will ensure that the start and end points of the gradient are marked within the boundaries of the plot area and not every detail BarMark.

Chart {
    ForEach(data, id: .month) {
        BarMark(
            x: .value("Month", String($0.month.prefix(3))),
            y: .value("Temperature", $0.temp)
        )
        .accessibilityLabel("($0.month)")
    }
    .foregroundStyle(
        .linearGradient(
            colors: [.blue, .red],
            startPoint: .bottom,
            endPoint: .top
        )
    )
    .alignsMarkStylesWithPlotArea()
}

We can now see that the coldest months have very little red tint while the hottest months have more.

Screenshot of a bar graph showing average daily temperature for the month in Christchurch with the bar markers filled with a linear gradient from blue to red

You can have the Complete code example For this article from our GitHub repository.

Swift charts are designed to work with SwiftUI, but you can still use them in a UIKit project. You can check out my recent book Integrating SwiftUI in UIKit Apps for ways to add SwiftUI views to an existing UIKit project to take full advantage of the new iOS 16 APIs.

If you enjoy our blog and would like to support us, you can Sponsor us on GitHub.

For blog updates and development tips, follow us on Twitter @nilcoalescing.

Source

Popular Articles