Skip to content

Commit

Permalink
WIP: Creating a data structure which propagets changes in data to the…
Browse files Browse the repository at this point in the history
… charts (#114)

* Creating a data structure which propagets changes in data to the charts

* Fixed appearing animation
  • Loading branch information
AppPear authored Jun 21, 2020
1 parent f0eea58 commit 5b4458a
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 110 deletions.
10 changes: 5 additions & 5 deletions Sources/SwiftUICharts/Base/Chart/AnyChartType.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import SwiftUI

struct AnyChartType: ChartType {
private let chartMaker: (ChartType.Configuration, ChartType.Style) -> AnyView
private let chartMaker: (ChartType.Data, ChartType.Style) -> AnyView

init<S: ChartType>(_ type: S) {
self.chartMaker = type.makeTypeErasedBody
}

func makeChart(configuration: ChartType.Configuration, style: ChartType.Style) -> AnyView {
self.chartMaker(configuration, style)
func makeChart(data: ChartType.Data, style: ChartType.Style) -> AnyView {
self.chartMaker(data, style)
}
}

fileprivate extension ChartType {
func makeTypeErasedBody(configuration: ChartType.Configuration, style: ChartType.Style) -> AnyView {
AnyView(makeChart(configuration: configuration, style: style))
func makeTypeErasedBody(data: ChartType.Data, style: ChartType.Style) -> AnyView {
AnyView(makeChart(data: data, style: style))
}
}
9 changes: 9 additions & 0 deletions Sources/SwiftUICharts/Base/Chart/ChartData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import SwiftUI

public class ChartData: ObservableObject {
@Published public var data: [Double] = []

public init(_ data: [Double]) {
self.data = data
}
}
4 changes: 2 additions & 2 deletions Sources/SwiftUICharts/Base/Chart/ChartType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import SwiftUI
public protocol ChartType {
associatedtype Body: View

func makeChart(configuration: Self.Configuration, style: Self.Style) -> Self.Body
func makeChart(data: Self.Data, style: Self.Style) -> Self.Body

typealias Configuration = ChartTypeConfiguration
typealias Data = ChartData
typealias Style = ChartStyle
}
5 changes: 0 additions & 5 deletions Sources/SwiftUICharts/Base/Chart/ChartTypeConfiguration.swift

This file was deleted.

16 changes: 11 additions & 5 deletions Sources/SwiftUICharts/Base/ChartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ public struct ChartView: View {
@Environment(\.chartType) private var chartType
@Environment(\.chartStyle) private var chartStyle

private var configuration: ChartTypeConfiguration
private var data: ChartData

public init(data: ChartData) {
self.data = data
}

public var body: some View {
self.chartType.makeChart(configuration: configuration, style: chartStyle)
self.chartType.makeChart(data: data, style: chartStyle)
}
}

extension ChartView {
public init(data: [Double]) {
self.configuration = ChartTypeConfiguration(data: data)
}
// public init(data: [Double]) {
// self.configuration = ChartTypeConfiguration(data: data)
// }


}
10 changes: 5 additions & 5 deletions Sources/SwiftUICharts/Charts/BarChart/BarChart.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import SwiftUI

public struct BarChart: ChartType {
public func makeChart(configuration: Self.Configuration, style: Self.Style) -> some View {
BarChartRow(data: configuration.data, style: style)
public func makeChart(data: Self.Data, style: Self.Style) -> some View {
BarChartRow(chartData: data, style: style)
}
public init() {}
}
Expand All @@ -11,17 +11,17 @@ struct BarChart_Previews: PreviewProvider {
static var previews: some View {
Group {
BarChart().makeChart(
configuration: .init(data: [0]),
data: .init([0]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
Group {
BarChart().makeChart(
configuration: .init(data: [1, 2, 3, 5, 1]),
data: .init([1, 2, 3, 5, 1]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
}.environment(\.colorScheme, .light)

Group {
BarChart().makeChart(
configuration: .init(data: [1, 2, 3]),
data: .init([1, 2, 3]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
}.environment(\.colorScheme, .dark)

Expand Down
64 changes: 41 additions & 23 deletions Sources/SwiftUICharts/Charts/BarChart/BarChartCell.swift
Original file line number Diff line number Diff line change
@@ -1,49 +1,67 @@
import SwiftUI

public struct BarChartCell: View {
@State var value: Double
@State var index: Int = 0
@State var width: Float
@State var numberOfDataPoints: Int
var value: Double
var index: Int = 0
var width: Float
var numberOfDataPoints: Int
var gradientColor: ColorGradient
var touchLocation: CGFloat

var cellWidth: Double {
return Double(width)/(Double(numberOfDataPoints) * 1.5)
}

@State var scaleValue: Double = 0
@Binding var touchLocation: CGFloat

@State var firstDisplay: Bool = true

public init( value: Double,
index: Int = 0,
width: Float,
numberOfDataPoints: Int,
gradientColor: ColorGradient,
touchLocation: CGFloat) {
self.value = value
self.index = index
self.width = width
self.numberOfDataPoints = numberOfDataPoints
self.gradientColor = gradientColor
self.touchLocation = touchLocation
}

public var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 4)
.fill(gradientColor.linearGradient(from: .bottom, to: .top))
}
.frame(width: CGFloat(self.cellWidth))
.scaleEffect(CGSize(width: 1, height: self.scaleValue), anchor: .bottom)
.onAppear {
self.scaleValue = self.value
}
.animation(Animation.spring().delay(self.touchLocation < 0 ? Double(self.index) * 0.04 : 0))
}
.frame(width: CGFloat(self.cellWidth))
.scaleEffect(CGSize(width: 1, height: self.firstDisplay ? 0.0 : self.value), anchor: .bottom)
.onAppear {
self.firstDisplay = false
}
.onDisappear {
self.firstDisplay = true
}
.transition(.slide)
.animation(Animation.spring().delay(self.touchLocation < 0 || !firstDisplay ? Double(self.index) * 0.04 : 0))
}
}

struct BarChartCell_Previews: PreviewProvider {
static var previews: some View {
Group {
BarChartCell(value: 0, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.greenRed, touchLocation: .constant(CGFloat()))
Group {
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.greenRed, touchLocation: .constant(CGFloat()))
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.whiteBlack, touchLocation: .constant(CGFloat()))
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient(.purple), touchLocation: .constant(CGFloat()))
BarChartCell(value: 0, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.greenRed, touchLocation: CGFloat())

BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.greenRed, touchLocation: CGFloat())
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.whiteBlack, touchLocation: CGFloat())
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient(.purple), touchLocation: CGFloat())
}

Group {
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.greenRed, touchLocation: .constant(CGFloat()))
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.whiteBlack, touchLocation: .constant(CGFloat()))
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient(.purple), touchLocation: .constant(CGFloat()))
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.greenRed, touchLocation: CGFloat())
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient.whiteBlack, touchLocation: CGFloat())
BarChartCell(value: 1, width: 50, numberOfDataPoints: 1, gradientColor: ColorGradient(.purple), touchLocation: CGFloat())
}.environment(\.colorScheme, .dark)
}

}
}
77 changes: 39 additions & 38 deletions Sources/SwiftUICharts/Charts/BarChart/BarChartRow.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import SwiftUI

public struct BarChartRow: View {
@State var data: [Double] = []
@ObservedObject var chartData: ChartData
@State var touchLocation: CGFloat = -1.0

enum Constant {
Expand All @@ -11,7 +11,7 @@ public struct BarChartRow: View {
var style: ChartStyle

var maxValue: Double {
guard let max = data.max() else {
guard let max = chartData.data.max() else {
return 1
}
return max != 0 ? max : 1
Expand All @@ -20,18 +20,18 @@ public struct BarChartRow: View {
public var body: some View {
GeometryReader { geometry in
HStack(alignment: .bottom,
spacing: (geometry.frame(in: .local).width - Constant.spacing) / CGFloat(self.data.count * 3)) {
ForEach(0..<self.data.count, id: \.self) { index in
BarChartCell(value: self.normalizedValue(index: index),
index: index,
width: Float(geometry.frame(in: .local).width - Constant.spacing),
numberOfDataPoints: self.data.count,
gradientColor: self.style.foregroundColor.rotate(for: index),
touchLocation: self.$touchLocation)
.scaleEffect(self.getScaleSize(touchLocation: self.touchLocation, index: index), anchor: .bottom)
.animation(.spring())

}
spacing: (geometry.frame(in: .local).width - Constant.spacing) / CGFloat(self.chartData.data.count * 3)) {
ForEach(0..<self.chartData.data.count, id: \.self) { index in
BarChartCell(value: self.normalizedValue(index: index),
index: index,
width: Float(geometry.frame(in: .local).width - Constant.spacing),
numberOfDataPoints: self.chartData.data.count,
gradientColor: self.style.foregroundColor.rotate(for: index),
touchLocation: self.touchLocation)
.scaleEffect(self.getScaleSize(touchLocation: self.touchLocation, index: index), anchor: .bottom)
.animation(Animation.easeIn(duration: 0.2))
}
// .drawingGroup()
}
.padding([.top, .leading, .trailing], 10)
.gesture(DragGesture()
Expand All @@ -46,37 +46,38 @@ public struct BarChartRow: View {
}

func normalizedValue(index: Int) -> Double {
return Double(data[index])/Double(maxValue)
print(chartData.data[index])
return Double(chartData.data[index])/Double(maxValue)
}

func getScaleSize(touchLocation: CGFloat, index: Int) -> CGSize {
if touchLocation > CGFloat(index)/CGFloat(self.data.count) &&
touchLocation < CGFloat(index+1)/CGFloat(self.data.count) {
if touchLocation > CGFloat(index)/CGFloat(chartData.data.count) &&
touchLocation < CGFloat(index+1)/CGFloat(chartData.data.count) {
return CGSize(width: 1.4, height: 1.1)
}
return CGSize(width: 1, height: 1)
}

}

struct BarChartRow_Previews: PreviewProvider {
static var previews: some View {
Group {
BarChartRow(data: [0], style: styleGreenRed)
Group {
BarChartRow(data: [1, 2, 3], style: styleGreenRed)
BarChartRow(data: [1, 2, 3], style: styleGreenRedWhiteBlack)
}
Group {
BarChartRow(data: [1, 2, 3], style: styleGreenRed)
BarChartRow(data: [1, 2, 3], style: styleGreenRedWhiteBlack)
}.environment(\.colorScheme, .dark)
}
}
}

private let styleGreenRed = ChartStyle(backgroundColor: .white, foregroundColor: .greenRed)

private let styleGreenRedWhiteBlack = ChartStyle(
backgroundColor: ColorGradient.init(.white),
foregroundColor: [ColorGradient.redBlack, ColorGradient.whiteBlack])
//struct BarChartRow_Previews: PreviewProvider {
// static var previews: some View {
// Group {
// BarChartRow(data: [0], style: styleGreenRed)
// Group {
// BarChartRow(data: [1, 2, 3], style: styleGreenRed)
// BarChartRow(data: [1, 2, 3], style: styleGreenRedWhiteBlack)
// }
// Group {
// BarChartRow(data: [1, 2, 3], style: styleGreenRed)
// BarChartRow(data: [1, 2, 3], style: styleGreenRedWhiteBlack)
// }.environment(\.colorScheme, .dark)
// }
// }
//}
//
//private let styleGreenRed = ChartStyle(backgroundColor: .white, foregroundColor: .greenRed)
//
//private let styleGreenRedWhiteBlack = ChartStyle(
// backgroundColor: ColorGradient.init(.white),
// foregroundColor: [ColorGradient.redBlack, ColorGradient.whiteBlack])
13 changes: 7 additions & 6 deletions Sources/SwiftUICharts/Charts/LineChart/Line.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import SwiftUI

public struct Line: View {
@State var frame: CGRect = .zero
@State var data: [Double]
@ObservedObject var chartData: ChartData

var style: ChartStyle

@State var showIndicator: Bool = false
Expand All @@ -11,11 +12,11 @@ public struct Line: View {
@State var showBackground: Bool = true
var curvedLines: Bool = true
var step: CGPoint {
return CGPoint.getStep(frame: frame, data: data)
return CGPoint.getStep(frame: frame, data: chartData.data)
}

var path: Path {
let points = data
let points = chartData.data

if curvedLines {
return Path.quadCurvedPathWithPoints(points: points,
Expand All @@ -27,7 +28,7 @@ public struct Line: View {
}

var closedPath: Path {
let points = data
let points = chartData.data

if curvedLines {
return Path.quadClosedCurvedPathWithPoints(points: points,
Expand Down Expand Up @@ -109,8 +110,8 @@ extension Line {
struct Line_Previews: PreviewProvider {
static var previews: some View {
Group {
Line(data: [1, 2, 3, 1, 2, 5, 7], style: blackLineStyle)
Line(data: [1, 2, 3, 1, 2, 5, 7], style: redLineStyle)
Line(chartData: ChartData([8, 23, 32, 7, 23, 43]), style: blackLineStyle)
Line(chartData: ChartData([8, 23, 32, 7, 23, 43]), style: redLineStyle)
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions Sources/SwiftUICharts/Charts/LineChart/LineChart.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import SwiftUI

public struct LineChart: ChartType {
public func makeChart(configuration: Self.Configuration, style: Self.Style) -> some View {
Line(data: configuration.data, style: style)
public func makeChart(data: Self.Data, style: Self.Style) -> some View {
Line(chartData: data, style: style)
}

public init() {}
Expand All @@ -12,17 +12,17 @@ struct LineChart_Previews: PreviewProvider {
static var previews: some View {
Group {
LineChart().makeChart(
configuration: .init(data: [0]),
data: .init([0]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient(.black)))
Group {
LineChart().makeChart(
configuration: .init(data: [1, 2, 3, 5, 1]),
data: .init([1, 2, 3, 5, 1]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient(.black)))
}.environment(\.colorScheme, .light)

Group {
LineChart().makeChart(
configuration: .init(data: [1, 2, 3]),
data: .init([1, 2, 3]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
}.environment(\.colorScheme, .dark)

Expand Down
Loading

0 comments on commit 5b4458a

Please sign in to comment.