Skip to content

Commit b48b701

Browse files
committed
feat: new protocol for chained functions, and added support for explicit Y ranges. X coming as well
1 parent d7e9802 commit b48b701

33 files changed

+538
-351
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import SwiftUI
2+
3+
public struct AxisLabels<Content: View>: View {
4+
var axisLabelsData = AxisLabelsData()
5+
let content: () -> Content
6+
// font
7+
// foregroundColor
8+
9+
public init(@ViewBuilder content: @escaping () -> Content) {
10+
self.content = content
11+
}
12+
13+
public var body: some View {
14+
HStack {
15+
VStack {
16+
ForEach(Array(axisLabelsData.axisYLabels.reversed().enumerated()), id: \.element) { index, axisYData in
17+
Text(axisYData)
18+
if index != axisLabelsData.axisYLabels.count - 1 {
19+
Spacer()
20+
}
21+
}
22+
}
23+
.padding([.trailing], 8.0)
24+
.padding([.bottom], axisLabelsData.axisXLabels.count > 0 ? 28.0 : 0)
25+
.frame(maxHeight: .infinity)
26+
VStack {
27+
self.content()
28+
HStack {
29+
ForEach(Array(axisLabelsData.axisXLabels.enumerated()), id: \.element) { index, axisXData in
30+
Text(axisXData)
31+
if index != axisLabelsData.axisXLabels.count - 1 {
32+
Spacer()
33+
}
34+
}
35+
}
36+
}
37+
.padding([.top, .bottom], 10.0)
38+
}
39+
}
40+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import SwiftUI
2+
3+
extension AxisLabels {
4+
public func setAxisYLabels(_ labels: [String]) -> AxisLabels {
5+
self.axisLabelsData.axisYLabels = labels
6+
return self
7+
}
8+
9+
public func setAxisXLabels(_ labels: [String]) -> AxisLabels {
10+
self.axisLabelsData.axisXLabels = labels
11+
return self
12+
}
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import SwiftUI
2+
3+
public final class AxisLabelsData: ObservableObject {
4+
@Published public var axisYLabels: [String] = []
5+
@Published public var axisXLabels: [String] = []
6+
7+
public init() {
8+
// no-op
9+
}
10+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import SwiftUI
22

33
/// Protocol for any type of chart, to get access to underlying data
4-
public protocol ChartBase {
4+
public protocol ChartBase: View {
55
var chartData: ChartData { get }
66
}

Sources/SwiftUICharts/Base/Chart/ChartData.swift

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,78 @@ import SwiftUI
22

33
/// An observable wrapper for an array of data for use in any chart
44
public class ChartData: ObservableObject {
5-
@Published public var data: [(String, Double)] = []
5+
@Published public var data: [(Double, Double)] = []
6+
public var rangeY: ClosedRange<Double>?
7+
public var rangeX: ClosedRange<Double>?
68

79
var points: [Double] {
8-
data.map { $0.1 }
10+
data.filter { rangeX?.contains($0.0) ?? true }.map { $0.1 }
911
}
1012

11-
var values: [String] {
12-
data.map { $0.0 }
13+
var values: [Double] {
14+
data.filter { rangeX?.contains($0.0) ?? true }.map { $0.0 }
1315
}
1416

1517
var normalisedPoints: [Double] {
1618
let absolutePoints = points.map { abs($0) }
17-
return points.map { $0 / (absolutePoints.max() ?? 1.0) }
19+
var maxPoint = absolutePoints.max()
20+
if let rangeY = rangeY {
21+
maxPoint = Double(rangeY.overreach)
22+
return points.map { ($0 - rangeY.lowerBound) / (maxPoint ?? 1.0) }
23+
}
24+
25+
return points.map { $0 / (maxPoint ?? 1.0) }
26+
}
27+
28+
var normalisedValues: [Double] {
29+
let absoluteValues = values.map { abs($0) }
30+
var maxValue = absoluteValues.max()
31+
if let rangeX = rangeX {
32+
maxValue = Double(rangeX.overreach)
33+
return values.map { ($0 - rangeX.lowerBound) / (maxValue ?? 1.0) }
34+
}
35+
36+
return values.map { $0 / (maxValue ?? 1.0) }
1837
}
1938

20-
var normalisedRange: Double {
21-
(normalisedPoints.max() ?? 0.0) - (normalisedPoints.min() ?? 0.0)
39+
var normalisedData: [(Double, Double)] {
40+
Array(zip(normalisedValues, normalisedPoints))
41+
}
42+
43+
var normalisedYRange: Double {
44+
if let _ = rangeY {
45+
return 1
46+
}
47+
48+
return (normalisedPoints.max() ?? 0.0) - (normalisedPoints.min() ?? 0.0)
49+
}
50+
51+
var normalisedXRange: Double {
52+
if let _ = rangeX {
53+
return 1
54+
}
55+
56+
return (normalisedValues.max() ?? 0.0) - (normalisedValues.min() ?? 0.0)
2257
}
2358

2459
var isInNegativeDomain: Bool {
25-
(points.min() ?? 0.0) < 0
60+
if let rangeY = rangeY {
61+
return rangeY.lowerBound < 0
62+
}
63+
64+
return (points.min() ?? 0.0) < 0
2665
}
2766

2867
/// Initialize with data array
2968
/// - Parameter data: Array of `Double`
30-
public init(_ data: [Double]) {
31-
self.data = data.map { ("", $0) }
69+
public init(_ data: [Double], rangeY: ClosedRange<FloatLiteralType>? = nil) {
70+
self.data = data.enumerated().map{ (index, value) in (Double(index), value) }
71+
self.rangeY = rangeY
3272
}
3373

34-
public init(_ data: [(String, Double)]) {
74+
public init(_ data: [(Double, Double)], rangeY: ClosedRange<FloatLiteralType>? = nil) {
3575
self.data = data
76+
self.rangeY = rangeY
3677
}
3778

3879
public init() {
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
import SwiftUI
22

3-
extension View where Self: ChartBase {
4-
5-
/// Set data for a chart
6-
/// - Parameter data: array of `Double`
7-
/// - Returns: modified `View` with data attached
8-
public func data(_ data: [Double]) -> some View {
9-
chartData.data = data.map { ("", $0) }
3+
extension ChartBase {
4+
public func data(_ data: [Double]) -> some ChartBase {
5+
chartData.data = data.enumerated().map{ (index, value) in (Double(index), value) }
106
return self
11-
.environmentObject(chartData)
12-
.environmentObject(ChartValue())
137
}
148

15-
public func data(_ data: [(String, Double)]) -> some View {
9+
public func data(_ data: [(Double, Double)]) -> some ChartBase {
1610
chartData.data = data
1711
return self
18-
.environmentObject(chartData)
19-
.environmentObject(ChartValue())
12+
}
13+
14+
public func rangeY(_ range: ClosedRange<FloatLiteralType>) -> some ChartBase{
15+
chartData.rangeY = range
16+
return self
17+
}
18+
19+
public func rangeX(_ range: ClosedRange<FloatLiteralType>) -> some ChartBase{
20+
chartData.rangeX = range
21+
return self
2022
}
2123
}

0 commit comments

Comments
 (0)