Customizing a Line Chart with SwiftUI Charts in iOS 16

Customizing a Line Chart with SwiftUI Charts in iOS 16

SwiftUI charts, introduced in iOS 16, can present data in an intuitive visual format and can be quickly created using SwiftUI charts. This article demonstrates several ways to customize line charts and combine them with area charts to display data.

Default Line Chart

Start by creating a default line chart using SwiftUI Charts[1] in Create a Line Chart with SwiftUI Charts in iOS 16. This shows step data for two different weeks, comparing the number of steps for each weekday.

 struct ChartView1 : View {
var body : some View {
VStack {
GroupBox ( "Line Chart - Daily Step Count" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.frame ( height : 400 )
}
.padding ( )

Spacer ( )
}
}
}

A default line chart created using SwiftUI Charts.

Changing the background behind the chart

Technically this has nothing to do with charts, but the background of ​GroupBox​​​ can be set using a color or GroupBoxStyle[2].

 struct YellowGroupBoxStyle : GroupBoxStyle {
func makeBody ( configuration : Configuration ) - > some View {
configuration.content
.padding ( .top , 30 )
.padding ( 20 )
.background ( Color ( hue : 0.10 , saturation : 0.10 , brightness : 0.98 ) )
.cornerRadius ( 20 )
.overlay (
configuration .label .padding ( 10 ) ,
alignment : .topLeading
)
}
}
 struct ChartView2 : View {
var body : some View {
VStack {
GroupBox ( "Line Chart - Daily Step Count" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.frame ( height : 400 )
}
// Add a style to the GroupBox
.groupBoxStyle ( YellowGroupBoxStyle ( ) )
.padding ( )

Spacer ( )
}
}
}

Sets styles for the GroupBox background.

Set the background of a drawing or chart

You can set a background for the chart plot area using chartPlotStyle[3] or for the entire chart using chartBackground[4].

Set the drawing area background

 GroupBox ( "Line Chart - Plot Background" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.chartPlotStyle { plotArea in
plotArea
.background ( .orange .opacity ( 0.1 ) )
.border ( .orange , width : 2 )
}
.frame ( height : 200 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )

Set the chart background

 GroupBox ( "Line Chart - Chart Background" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.chartBackground { chartProxy in
Color .red .opacity ( 0.1 )
}
.frame ( height : 200 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )

Set the background of the plot area and chart

 GroupBox ( "Line Chart - Plot & Chart Backgroundt" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.chartBackground { chartProxy in
Color .red .opacity ( 0.1 )
}
.chartPlotStyle { plotArea in
plotArea
.background ( .orange .opacity ( 0.1 ) )
.border ( .orange , width : 2 )
}

.frame ( height : 200 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )

Use SwiftUI Charts to set backgrounds on the plotting area and full chart.

Move the Y axis to the left

Move the Y axis to the left edge (leading).

You can hide axes or adjust their position, such as placing the Y axis on the left side of the chart (leading). The Y axis is displayed on the right side of the chart (trailing) by default. You can use the AxisMarks[5] of chartYAxis to place it on the left side. You can also hide an axis completely by setting its visibility property to hidden.

 struct ChartView4 : View {
var body : some View {
VStack {
GroupBox ( "Line Chart - Y-axis on leading edge" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.chartPlotStyle { plotArea in
plotArea
.background ( Color ( hue : 0.12 , saturation : 0.10 , brightness : 0.92 ) )
}
// Place the y-axis on the leading side of the chart
.chartYAxis {
AxisMarks ( position : .leading )
}
.frame ( height : 400 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )
.padding ( )

Spacer ( )
}
}
}

Use SwiftUI Charts to place the Y-axis on the left side of the chart.

Move the chart legend

By default, a chart legend appears at the bottom of the chart. Legends can be placed on any side of the chart or in multiple locations on the chart.

 GroupBox ( "Line Chart - legend overlay on top center" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
// Position the Legend
.chartLegend ( position : .overlay , alignment : .top )
.chartPlotStyle { plotArea in
plotArea
.background ( Color ( hue : 0.12 , saturation : 0.10 , brightness : 0.92 ) )
}
.chartYAxis ( ) {
AxisMarks ( position : .leading )
}
.frame ( height : 200 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )
 GroupBox ( "Line Chart - legend trailing center" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
// Position the Legend
.chartLegend ( position : .trailing , alignment : .center , spacing : 10 )
.chartPlotStyle { plotArea in
plotArea
.background ( Color ( hue : 0.12 , saturation : 0.10 , brightness : 0.92 ) )
}
.chartYAxis ( ) {
AxisMarks ( position : .leading )
}
.frame ( height : 200 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )

Change the line style

A line chart connects the data points on the chart with a straight line. The interpolationMethod[6] function can connect the data points with a curve in various ways.

 struct ChartView6 : View {
var body : some View {
VStack ( spacing : 30 ) {
GroupBox ( "Line Chart - Curved line connector" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
// Use curved line to join points
.interpolationMethod ( .catmullRom )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.chartLegend ( position : .overlay , alignment : .top )
.chartPlotStyle { plotArea in
plotArea
.background ( Color ( hue : 0.12 , saturation : 0.10 , brightness : 0.92 ) )
}
.chartYAxis ( ) {
AxisMarks ( position : .leading )
}
.frame ( height : 300 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )

GroupBox ( "Line Chart - Step line connector" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
// Use step line to join points
.interpolationMethod ( .stepCenter )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
.chartLegend ( position : .overlay , alignment : .top )
.chartPlotStyle { plotArea in
plotArea
.background ( Color ( hue : 0.12 , saturation : 0.10 , brightness : 0.92 ) )
}
.chartYAxis ( ) {
AxisMarks ( position : .leading )
}
.frame ( height : 300 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )


Spacer ( )
}
.padding ( )
}
}

Change the line style that connects data points in a SwiftUI chart.

Change the color of the line

You can use chartForegroundStyleScale [7] to set the default color of the lines in a line chart.

 struct ChartView7 : View {
var body : some View {
VStack ( ) {
GroupBox ( "Line Chart - Custom line colors" ) {
Chart {
ForEach ( stepData , id : \ .period ) { steps in
ForEach ( steps .data ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.foregroundStyle ( by : .value ( "Week" , steps .period ) )
.interpolationMethod ( .catmullRom )
.symbol ( by : .value ( "Week" , steps .period ) )
.symbolSize ( 30 )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
}
// Set color for each data in the chart
.chartForegroundStyleScale ( [
"Current Week" : Color ( hue : 0.33 , saturation : 0.81 , brightness : 0.76 ) ,
"Previous Week" : Color ( hue : 0.69 , saturation : 0.19 , brightness : 0.79 )
] )
.chartLegend ( position : .overlay , alignment : .top )
.chartPlotStyle { plotArea in
plotArea
.background ( Color ( hue : 0.12 , saturation : 0.10 , brightness : 0.92 ) )
}
.chartYAxis ( ) {
AxisMarks ( position : .leading )
}
.frame ( height : 400 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )

Spacer ( )
}
.padding ( )
}
}

Set custom colors for lines in SwiftUI charts.

Change the line style

The lines on the line chart can be modified by setting ​lineStyle​​​ using StrokeStyle[8]. Two different styles are used in the step data to distinguish the data from the previous week from the current data. In addition, a custom symbol is set for the data points on the chart.

 struct ChartView8 : View {
let prevColor = Color ( hue : 0.69 , saturation : 0.19 , brightness : 0.79 )
let curColor = Color ( hue : 0.33 , saturation : 0.81 , brightness : 0.76 )
var body : some View {
VStack ( ) {
GroupBox ( "Line Chart - Line color and format" ) {
Chart {
ForEach ( previousWeek ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.interpolationMethod ( .catmullRom )
.foregroundStyle ( prevColor )
.foregroundStyle ( by : .value ( "Week" , "Previous Week" ) )
.lineStyle ( StrokeStyle ( lineWidth : 3 , dash : [ 5 , 10 ] ) )
.symbol ( ) {
Rectangle ( )
.fill ( prevColor )
.frame ( width : 8 , height : 8 )
}
.symbolSize ( 30 )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
ForEach ( currentWeek ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.interpolationMethod ( .catmullRom )
.foregroundStyle ( curColor )
.foregroundStyle ( by : .value ( "Week" , "Current Week" ) )
.lineStyle ( StrokeStyle ( lineWidth : 3 ) )
.symbol ( ) {
Circle ( )
.fill ( curColor )
.frame ( width : 10 )
}
.symbolSize ( 30 )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
// Set the Y axis scale
.chartYScale ( domain : 0 ... 30000 )
.chartForegroundStyleScale ( [
"Current Week" : curColor ,
"Previous Week" : prevColor
] )
.chartLegend ( position : .overlay , alignment : .top )
.chartPlotStyle { plotArea in
plotArea
.background ( Color ( hue : 0.12 , saturation : 0.10 , brightness : 0.92 ) )
}
.chartYAxis ( ) {
AxisMarks ( position : .leading )
}
.frame ( height : 400 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )
Spacer ( )
}
.padding ( )
}
}

Set a custom line style for a data set in a SwiftUI chart.

Combining area chart and line chart

Finally, a line chart is combined with an area chart to help differentiate one data set from another. An area chart is added for only the current week of data, and the areas are colored below the gradient line.

 struct ChartView9 : View {
var body : some View {
let prevColor = Color ( hue : 0.69 , saturation : 0.19 , brightness : 0.79 )
let curColor = Color ( hue : 0.33 , saturation : 0.81 , brightness : 0.76 )
let curGradient = LinearGradient (
gradient : Gradient (
colors : [
curColor .opacity ( 0.5 ) ,
curColor .opacity ( 0.2 ) ,
curColor .opacity ( 0.05 ) ,
]
) ,
startPoint : .top ,
endPoint : .bottom
)
VStack ( ) {
GroupBox ( "Line Chart - Combine Line and Area chart" ) {
Chart {
ForEach ( previousWeek ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.interpolationMethod ( .catmullRom )
.foregroundStyle ( prevColor )
.foregroundStyle ( by : .value ( "Week" , "Previous Week" ) )
.lineStyle ( StrokeStyle ( lineWidth : 3 , dash : [ 5 , 10 ] ) )
.symbol ( ) {
Rectangle ( )
.fill ( prevColor )
.frame ( width : 8 , height : 8 )
}
.symbolSize ( 30 )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
ForEach ( currentWeek ) {
LineMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.interpolationMethod ( .catmullRom )
.foregroundStyle ( curColor )
.foregroundStyle ( by : .value ( "Week" , "Current Week" ) )
.lineStyle ( StrokeStyle ( lineWidth : 3 ) )
.symbol ( ) {
Circle ( )
.fill ( curColor )
.frame ( width : 10 )
}
.symbolSize ( 30 )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )

AreaMark (
x : .value ( "Week Day" , $0 .shortDay ) ,
y : .value ( "Step Count" , $0 .steps )
)
.interpolationMethod ( .catmullRom )
.foregroundStyle ( curGradient )
.foregroundStyle ( by : .value ( "Week" , "Current Week" ) )
.accessibilityLabel ( "\( $0 .weekdayString )" )
.accessibilityValue ( "\( $0 .steps ) Steps" )
}
}
// Set the Y axis scale
.chartYScale ( domain : 0 ... 30000 )

.chartForegroundStyleScale ( [
"Current Week" : curColor ,
"Previous Week" : prevColor
] )
.chartLegend ( position : .overlay , alignment : .top )
.chartPlotStyle { plotArea in
plotArea
.background ( Color ( hue : 0.12 , saturation : 0.10 , brightness : 0.92 ) )
}
.chartYAxis ( ) {
AxisMarks ( position : .leading )
}
.frame ( height : 400 )
}
.groupBoxStyle ( YellowGroupBoxStyle ( ) )
Spacer ( )
}
.padding ( )
}
}

Combine a line chart with an area chart using custom colors in SwiftUI Charts.

in conclusion

SwiftUI Charts is currently in beta and there may be some issues with Xcode performance and compiling some chart options, but it's easy to get started with charts. The help documentation is available and good, but I would like to see more code examples. It has a lot of potential to customize the charts and present data in an intuitive way to the users of your app.

References

[1] Charts: https://developer.apple.com/documentation/charts​.

[2] GroupBoxStyle: https://developer.apple.com/documentation/swiftui/groupboxstyle​.

[3] chartPlotStyle: https://developer.apple.com/documentation/swiftui/view/chartplotstyle(content:)​.

[4] chartBackground: https://developer.apple.com/documentation/swiftui/view/chartplotstyle(content:)​.

[5] AxisMarks: https://developer.apple.com/documentation/swiftui/view/chartyaxis(content:)​.

[6] interpolationMethod: https://developer.apple.com/documentation/charts/chartcontent/interpolationmethod(_:)​.

[7] chartForegroundStyleScale: https://developer.apple.com/documentation/swiftui/view/chartforegroundstylescale(_:)?changes=_10​.

[8] StrokeStyle: https://developer.apple.com/documentation/swiftui/strokestyle​.

<<:  Apple releases quick security response update for iOS 16.2 Beta users

>>:  Async/Await in Swift — Detailed Code Examples

Recommend

What are some tips for new Tik Tok live broadcasts to avoid dull audiences?

For many new Douyin users, they naturally hope to...

How to write good ideas efficiently through information flow?

Recently I received a secret report: it said that...

Python Quantitative Finance Practice by Wall Street Masters

Introduction to Wall Street Master-level Python Q...

How to write product and promotion copy for Double Eleven?

The annual large-scale shopping festival is comin...

Running thousands of miles! How can this locust fly so fast?

Produced by: Science Popularization China Author:...