From 29c9ad024e2e2fa28b5a8afd8b81a1e0cf7b31b6 Mon Sep 17 00:00:00 2001 From: Kunal Verma Date: Thu, 20 Jan 2022 08:25:27 +0530 Subject: [PATCH 1/4] Negative Value Visualisation fix for Bar/Grouped/Horizontal Bar Charts --- Sources/SwiftUICharts/BarChart/Views/BarChart.swift | 5 ++++- Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift | 5 ++++- .../SwiftUICharts/BarChart/Views/HorizontalBarChart.swift | 6 ++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Sources/SwiftUICharts/BarChart/Views/BarChart.swift b/Sources/SwiftUICharts/BarChart/Views/BarChart.swift index 60dc208f..c785f675 100644 --- a/Sources/SwiftUICharts/BarChart/Views/BarChart.swift +++ b/Sources/SwiftUICharts/BarChart/Views/BarChart.swift @@ -1,6 +1,6 @@ // // BarChart.swift -// +// // // Created by Will Dale on 11/01/2021. // @@ -71,5 +71,8 @@ public struct BarChart: View where ChartData: BarChartData { } } else { CustomNoDataView(chartData: chartData) } } + .if(chartData.minValue.isLess(than: 0)) { + $0.scaleEffect(y: chartData.maxValue/(chartData.maxValue - chartData.minValue), anchor: .top) + } } } diff --git a/Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift b/Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift index b667c8af..3a2fdd34 100644 --- a/Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift +++ b/Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift @@ -1,6 +1,6 @@ // // GroupedBarChart.swift -// +// // // Created by Will Dale on 25/01/2021. // @@ -73,6 +73,9 @@ public struct GroupedBarChart: View where ChartData: GroupedBarChartD } } else { CustomNoDataView(chartData: chartData) } } + .if(chartData.minValue.isLess(than: 0)) { + $0.scaleEffect(y: chartData.maxValue/(chartData.maxValue - chartData.minValue), anchor: .top) + } } } diff --git a/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift b/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift index d13bcca1..fe03382f 100644 --- a/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift +++ b/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift @@ -1,6 +1,6 @@ // // HorizontalBarChart.swift -// +// // // Created by Will Dale on 26/04/2021. // @@ -29,12 +29,14 @@ public struct HorizontalBarChart: View where ChartData: HorizontalBar HorizontalBarChartDataPointSubView(chartData: chartData) .accessibilityLabel(LocalizedStringKey(chartData.metadata.title)) } - } // Needed for axes label frames .onChange(of: geo.frame(in: .local)) { value in self.chartData.viewData.chartSize = value } + .if(chartData.minValue.isLess(than: 0)) { + $0.scaleEffect(x: chartData.maxValue/(chartData.maxValue - chartData.minValue), anchor: .trailing) + } } else { CustomNoDataView(chartData: chartData) } } } From 4e3b9a8232bb53072ae3e08a9dac56669d0b344e Mon Sep 17 00:00:00 2001 From: Kunal Verma Date: Thu, 20 Jan 2022 09:29:50 +0530 Subject: [PATCH 2/4] Explicit CGFloat conversion for iOS/tvOS 14 --- Sources/SwiftUICharts/BarChart/Views/BarChart.swift | 2 +- Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift | 2 +- Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/SwiftUICharts/BarChart/Views/BarChart.swift b/Sources/SwiftUICharts/BarChart/Views/BarChart.swift index c785f675..3b9847fa 100644 --- a/Sources/SwiftUICharts/BarChart/Views/BarChart.swift +++ b/Sources/SwiftUICharts/BarChart/Views/BarChart.swift @@ -72,7 +72,7 @@ public struct BarChart: View where ChartData: BarChartData { } else { CustomNoDataView(chartData: chartData) } } .if(chartData.minValue.isLess(than: 0)) { - $0.scaleEffect(y: chartData.maxValue/(chartData.maxValue - chartData.minValue), anchor: .top) + $0.scaleEffect(y: CGFloat(chartData.maxValue/(chartData.maxValue - chartData.minValue)), anchor: .top) } } } diff --git a/Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift b/Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift index 3a2fdd34..394802d6 100644 --- a/Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift +++ b/Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift @@ -74,7 +74,7 @@ public struct GroupedBarChart: View where ChartData: GroupedBarChartD } else { CustomNoDataView(chartData: chartData) } } .if(chartData.minValue.isLess(than: 0)) { - $0.scaleEffect(y: chartData.maxValue/(chartData.maxValue - chartData.minValue), anchor: .top) + $0.scaleEffect(y: CGFloat(chartData.maxValue/(chartData.maxValue - chartData.minValue)), anchor: .top) } } } diff --git a/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift b/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift index fe03382f..c873b9a4 100644 --- a/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift +++ b/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift @@ -35,7 +35,7 @@ public struct HorizontalBarChart: View where ChartData: HorizontalBar self.chartData.viewData.chartSize = value } .if(chartData.minValue.isLess(than: 0)) { - $0.scaleEffect(x: chartData.maxValue/(chartData.maxValue - chartData.minValue), anchor: .trailing) + $0.scaleEffect(x: CGFloat(chartData.maxValue/(chartData.maxValue - chartData.minValue)), anchor: .trailing) } } else { CustomNoDataView(chartData: chartData) } } From 4f4e645a9ed2856013953d7c908af3b735cb5f73 Mon Sep 17 00:00:00 2001 From: Kunal Verma Date: Thu, 20 Jan 2022 09:33:02 +0530 Subject: [PATCH 3/4] Minor Fix --- .../SwiftUICharts/BarChart/Views/HorizontalBarChart.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift b/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift index c873b9a4..ade89882 100644 --- a/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift +++ b/Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift @@ -34,10 +34,10 @@ public struct HorizontalBarChart: View where ChartData: HorizontalBar .onChange(of: geo.frame(in: .local)) { value in self.chartData.viewData.chartSize = value } - .if(chartData.minValue.isLess(than: 0)) { - $0.scaleEffect(x: CGFloat(chartData.maxValue/(chartData.maxValue - chartData.minValue)), anchor: .trailing) - } } else { CustomNoDataView(chartData: chartData) } } + .if(chartData.minValue.isLess(than: 0)) { + $0.scaleEffect(x: CGFloat(chartData.maxValue/(chartData.maxValue - chartData.minValue)), anchor: .trailing) + } } } From 97193bd6a53203ab8545275c6bad210a30dfa823 Mon Sep 17 00:00:00 2001 From: Kunal Verma Date: Sun, 30 Jan 2022 20:05:07 +0530 Subject: [PATCH 4/4] Fix Touch Point Location for negative value charts --- .../Models/ChartData/BarChartData.swift | 16 +++++++++++----- .../Models/ChartData/GroupedBarChartData.swift | 16 +++++++++++----- .../ChartData/HorizontalBarChartData.swift | 18 ++++++++++-------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift b/Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift index b69e986c..32b214ca 100644 --- a/Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift +++ b/Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift @@ -1,6 +1,6 @@ // // BarChartData.swift -// +// // // Created by Will Dale on 23/01/2021. // @@ -41,7 +41,7 @@ public final class BarChartData: CTBarChartDataProtocol, GetDataProtocol, Publis /// - dataSets: Data to draw and style the bars. /// - metadata: Data model containing the charts Title, Subtitle and the Title for Legend. /// - xAxisLabels: Labels for the X axis instead of the labels in the data points. - /// - yAxisLabels: Labels for the Y axis instead of the labels generated from data point values. + /// - yAxisLabels: Labels for the Y axis instead of the labels generated from data point values. /// - barStyle: Control for the aesthetic of the bar chart. /// - chartStyle: The style data for the aesthetic of the chart. /// - noDataText: Customisable Text to display when where is not enough data to draw the chart. @@ -148,11 +148,17 @@ public final class BarChartData: CTBarChartDataProtocol, GetDataProtocol, Publis public final func getPointLocation(dataSet: BarDataSet, touchLocation: CGPoint, chartSize: CGRect) -> CGPoint? { let xSection: CGFloat = chartSize.width / CGFloat(dataSet.dataPoints.count) - let ySection: CGFloat = chartSize.height / CGFloat(self.maxValue) + var ySection: CGFloat = chartSize.height / CGFloat(self.maxValue) let index: Int = Int((touchLocation.x) / xSection) if index >= 0 && index < dataSet.dataPoints.count { - return CGPoint(x: (CGFloat(index) * xSection) + (xSection / 2), - y: (chartSize.size.height - CGFloat(dataSet.dataPoints[index].value) * ySection)) + let x = (CGFloat(index) * xSection) + (xSection / 2) + var y = (chartSize.size.height - CGFloat(dataSet.dataPoints[index].value) * ySection) + if self.minValue.isLess(than: 0) { + ySection = chartSize.height / (CGFloat(self.maxValue) - CGFloat(self.minValue)) + y = (chartSize.size.height - (CGFloat(dataSet.dataPoints[index].value) * ySection) + (CGFloat(self.minValue) * ySection)) + } + return CGPoint(x: x, + y: y) } return nil } diff --git a/Sources/SwiftUICharts/BarChart/Models/ChartData/GroupedBarChartData.swift b/Sources/SwiftUICharts/BarChart/Models/ChartData/GroupedBarChartData.swift index 011416ff..9cc404f3 100644 --- a/Sources/SwiftUICharts/BarChart/Models/ChartData/GroupedBarChartData.swift +++ b/Sources/SwiftUICharts/BarChart/Models/ChartData/GroupedBarChartData.swift @@ -1,6 +1,6 @@ // // MultiBarChartData.swift -// +// // // Created by Will Dale on 26/01/2021. // @@ -49,7 +49,7 @@ public final class GroupedBarChartData: CTMultiBarChartDataProtocol, GetDataProt /// - groups: Information for how to group the data points. /// - metadata: Data model containing the charts Title, Subtitle and the Title for Legend. /// - xAxisLabels: Labels for the X axis instead of the labels in the data points. - /// - yAxisLabels: Labels for the Y axis instead of the labels generated from data point values. + /// - yAxisLabels: Labels for the Y axis instead of the labels generated from data point values. /// - barStyle: Control for the aesthetic of the bar chart. /// - chartStyle: The style data for the aesthetic of the chart. /// - noDataText: Customisable Text to display when where is not enough data to draw the chart. @@ -185,7 +185,7 @@ public final class GroupedBarChartData: CTMultiBarChartDataProtocol, GetDataProt // Make those sections take account of spacing between groups. let xSection: CGFloat = superXSection - compensation - let ySection: CGFloat = chartSize.height / CGFloat(self.maxValue) + var ySection: CGFloat = chartSize.height / CGFloat(self.maxValue) let index: Int = Int((touchLocation.x - CGFloat(groupSpacing * CGFloat(superIndex))) / xSection) @@ -197,8 +197,14 @@ public final class GroupedBarChartData: CTMultiBarChartDataProtocol, GetDataProt let element: CGFloat = (CGFloat(subIndex) * xSubSection) + (xSubSection / 2) let section: CGFloat = (superXSection * CGFloat(superIndex)) let spacing: CGFloat = ((groupSpacing / CGFloat(dataSets.dataSets.count)) * CGFloat(superIndex)) - return CGPoint(x: element + section + spacing, - y: (chartSize.height - CGFloat(subDataSet.dataPoints[subIndex].value) * ySection)) + let x = element + section + spacing + var y = (chartSize.height - CGFloat(subDataSet.dataPoints[subIndex].value) * ySection) + if self.minValue.isLess(than: 0) { + ySection = chartSize.height / (CGFloat(self.maxValue) - CGFloat(self.minValue)) + y = (chartSize.height - (CGFloat(subDataSet.dataPoints[subIndex].value) * ySection) + (CGFloat(self.minValue) * ySection)) + } + return CGPoint(x: x, + y: y) } } return nil diff --git a/Sources/SwiftUICharts/BarChart/Models/ChartData/HorizontalBarChartData.swift b/Sources/SwiftUICharts/BarChart/Models/ChartData/HorizontalBarChartData.swift index 6196473c..20e25468 100644 --- a/Sources/SwiftUICharts/BarChart/Models/ChartData/HorizontalBarChartData.swift +++ b/Sources/SwiftUICharts/BarChart/Models/ChartData/HorizontalBarChartData.swift @@ -1,6 +1,6 @@ // // HorizontalBarChartData.swift -// +// // // Created by Will Dale on 26/04/2021. // @@ -120,10 +120,6 @@ public final class HorizontalBarChartData: CTHorizontalBarChartDataProtocol, Get Spacer() .frame(minHeight: 0, maxHeight: 500) } - if self.chartStyle.xAxisLabelPosition == .bottom { - Spacer() - .frame(height: yAxisPaddingHeight + 8) // Why 8 ? - } } case .chartData: @@ -187,11 +183,17 @@ public final class HorizontalBarChartData: CTHorizontalBarChartDataProtocol, Get public final func getPointLocation(dataSet: BarDataSet, touchLocation: CGPoint, chartSize: CGRect) -> CGPoint? { let ySection: CGFloat = chartSize.height / CGFloat(dataSet.dataPoints.count) - let xSection: CGFloat = chartSize.width / CGFloat(self.maxValue) + var xSection: CGFloat = chartSize.width / CGFloat(self.maxValue) let index: Int = Int((touchLocation.y) / ySection) if index >= 0 && index < dataSet.dataPoints.count { - return CGPoint(x: (CGFloat(dataSet.dataPoints[index].value) * xSection), - y: (CGFloat(index) * ySection) + (ySection / 2)) + var x = (CGFloat(dataSet.dataPoints[index].value) * xSection) + let y = (CGFloat(index) * ySection) + (ySection / 2) + if self.minValue.isLess(than: 0) { + xSection = chartSize.width / (CGFloat(self.maxValue) - CGFloat(self.minValue)) + x = (CGFloat(dataSet.dataPoints[index].value) * xSection) - (CGFloat(self.minValue) * xSection) + } + return CGPoint(x: x, + y: y) } return nil }