Skip to content

Commit

Permalink
Merge pull request #168 from kunalverma25/BarChartsNegativeValueFix
Browse files Browse the repository at this point in the history
Negative Value Visualisation fix for Bar/Grouped/Horizontal Bar Charts
  • Loading branch information
willdale authored Mar 12, 2022
2 parents f395a76 + 97193bd commit 0a538b2
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 22 deletions.
16 changes: 11 additions & 5 deletions Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// BarChartData.swift
//
//
//
// Created by Will Dale on 23/01/2021.
//
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// MultiBarChartData.swift
//
//
//
// Created by Will Dale on 26/01/2021.
//
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// HorizontalBarChartData.swift
//
//
//
// Created by Will Dale on 26/04/2021.
//
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
}
Expand Down
5 changes: 4 additions & 1 deletion Sources/SwiftUICharts/BarChart/Views/BarChart.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// BarChart.swift
//
//
//
// Created by Will Dale on 11/01/2021.
//
Expand Down Expand Up @@ -71,5 +71,8 @@ public struct BarChart<ChartData>: View where ChartData: BarChartData {
}
} else { CustomNoDataView(chartData: chartData) }
}
.if(chartData.minValue.isLess(than: 0)) {
$0.scaleEffect(y: CGFloat(chartData.maxValue/(chartData.maxValue - chartData.minValue)), anchor: .top)
}
}
}
5 changes: 4 additions & 1 deletion Sources/SwiftUICharts/BarChart/Views/GroupedBarChart.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// GroupedBarChart.swift
//
//
//
// Created by Will Dale on 25/01/2021.
//
Expand Down Expand Up @@ -73,6 +73,9 @@ public struct GroupedBarChart<ChartData>: View where ChartData: GroupedBarChartD
}
} else { CustomNoDataView(chartData: chartData) }
}
.if(chartData.minValue.isLess(than: 0)) {
$0.scaleEffect(y: CGFloat(chartData.maxValue/(chartData.maxValue - chartData.minValue)), anchor: .top)
}
}
}

Expand Down
6 changes: 4 additions & 2 deletions Sources/SwiftUICharts/BarChart/Views/HorizontalBarChart.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// HorizontalBarChart.swift
//
//
//
// Created by Will Dale on 26/04/2021.
//
Expand Down Expand Up @@ -29,13 +29,15 @@ public struct HorizontalBarChart<ChartData>: 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
}
} else { CustomNoDataView(chartData: chartData) }
}
.if(chartData.minValue.isLess(than: 0)) {
$0.scaleEffect(x: CGFloat(chartData.maxValue/(chartData.maxValue - chartData.minValue)), anchor: .trailing)
}
}
}

0 comments on commit 0a538b2

Please sign in to comment.