Fill bar marks with gradient in Swift Charts

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 daily mean temperature in Christchurch for each month of the year. We will also fill the bar 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 whole plot area rather then fill each bar mark individually to achieve the desired effect. Here is what our final chart will look like.

Screenshot of a bar chart showing daily mean temperature per month in Christchurch with the bar marks filled with a linear gradient from blue to red

We'll start by creating a basic bar chart to plot the following data. The 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'm using strings for months of the year and doubles for temperature for simplicity here. In a real app you might want to store the temperature values using the Measurement type. You can find out how to plot values of type Measurement in one of my previous posts Using Measurements from Foundation for values in Swift Charts.

Swift Gems by Natalia Panferova book coverSwift Gems by Natalia Panferova book cover

Level up your Swift skills!$35

100+ tips to take your Swift code to the next level

Swift Gemsby Natalia Panferova

  • Advanced Swift techniques for experienced developers bypassing basic tutorials
  • Curated, actionable tips ready for immediate integration into any Swift project
  • Strategies to improve code quality, structure, and performance across all platforms

Level up your Swift skills!

100+ tips to take your Swift code to the next level

Swift Gems by Natalia Panferova book coverSwift Gems by Natalia Panferova book cover

Swift Gems

by Natalia Panferova

$35

Our basic chart will have the month of the year on the x-axis and the mean temperature value on the y-axis. We'll show the abbreviated month string on the chart but provide the full string for Voice Over users with the accessibilityLabel() modifier applied to each 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 daily mean temperature per month in Christchurch with the bar marks filled with 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 color to red to visualize the cold and warm temperatures better.

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 check the result now, we'll see that by default the gradient is applied from the bottom to the top of each individual bar. This is not what we want, since it doesn't correlate with the temperature values correctly. The warmest temperatures throughout the year should have more red tint than colder temperatures.

Screenshot of a bar chart showing daily mean temperature per month in Christchurch with the bar marks filled with a linear gradient from blue to red starting and ending within the bounds of each mark

To fix it we can apply the alignsMarkStylesWithPlotArea() modifier to the style. This will ensure that the start and the end points of the gradient are marked within the plot area’s bounds rather then each individual 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 see now that the coldest months have very little red tint while the warmest ones have more.

Screenshot of a bar chart showing daily mean temperature per month in Christchurch with the bar marks filled with a linear gradient from blue to red

You can get the complete code example for this article from our GitHub repository.

Swift Charts are designed to work seamlessly with SwiftUI, but they can also be integrated into a UIKit project. For detailed guidance on incorporating SwiftUI views into your existing UIKit app, check out my book Integrating SwiftUI into UIKit Apps. Additionally, if you're eager to enhance your Swift programming skills, my latest book Swift Gems offers over a hundred advanced tips and techniques to take your Swift code to the next level.

Integrating SwiftUI into UIKit Apps by Natalia Panferova book coverIntegrating SwiftUI into UIKit Apps by Natalia Panferova book cover

Enhance older apps with SwiftUI!$45

A detailed guide on gradually adopting SwiftUI in UIKit projects

Updated for iOS 18 and Xcode 16!

Integrating SwiftUI into UIKit Appsby Natalia Panferova

  • Upgrade your apps with new features like Swift Charts and Widgets
  • Support older iOS versions with effective backward-compatible strategies
  • Seamlessly bridge state and data between UIKit and SwiftUI using the latest APIs

Enhance older apps with SwiftUI!

A detailed guide on gradually adopting SwiftUI in UIKit projects

Integrating SwiftUI into UIKit Apps by Natalia Panferova book coverIntegrating SwiftUI into UIKit Apps by Natalia Panferova book cover

Integrating SwiftUI
into UIKit Apps

by Natalia Panferova

Updated for iOS 18 and Xcode 16!

$45