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. |