Compare commits

...

1 Commits

Author SHA1 Message Date
Andras Samu 40f9210205 Refactor Chart base 2020-07-25 18:56:08 +02:00
20 changed files with 92 additions and 268 deletions
@@ -1,19 +1,19 @@
import SwiftUI
public struct CardView<Content: View>: View {
@Environment(\.chartStyle) private var chartStyle
public struct CardView<Content: View>: View, ChartBase {
public var chartData = ChartData()
let content: () -> Content
@EnvironmentObject var style: ChartStyle
public init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
public var body: some View {
ZStack{
Rectangle()
RoundedRectangle(cornerRadius: 20)
.fill(Color.white)
.cornerRadius(20)
.shadow(color: Color.gray, radius: 8)
VStack {
self.content()
@@ -1,19 +0,0 @@
import SwiftUI
struct AnyChartType: ChartType {
private let chartMaker: (ChartType.Data, ChartType.Style) -> AnyView
init<S: ChartType>(_ type: S) {
self.chartMaker = type.makeTypeErasedBody
}
func makeChart(data: ChartType.Data, style: ChartType.Style) -> AnyView {
self.chartMaker(data, style)
}
}
fileprivate extension ChartType {
func makeTypeErasedBody(data: ChartType.Data, style: ChartType.Style) -> AnyView {
AnyView(makeChart(data: data, style: style))
}
}
@@ -0,0 +1,5 @@
import SwiftUI
public protocol ChartBase {
var chartData: ChartData { get }
}
@@ -6,4 +6,8 @@ public class ChartData: ObservableObject {
public init(_ data: [Double]) {
self.data = data
}
public init() {
self.data = []
}
}
@@ -1,11 +0,0 @@
import SwiftUI
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol ChartType {
associatedtype Body: View
func makeChart(data: Self.Data, style: Self.Style) -> Self.Body
typealias Data = ChartData
typealias Style = ChartStyle
}
@@ -1,22 +0,0 @@
import SwiftUI
public struct ChartView: View {
@Environment(\.chartType) private var chartType
@Environment(\.chartStyle) private var chartStyle
private var data: ChartData
public init(data: ChartData) {
self.data = data
}
public var body: some View {
self.chartType.makeChart(data: data, style: chartStyle)
}
}
extension ChartView {
public init(points: [Double]) {
self.data = ChartData(points)
}
}
@@ -1,10 +1,3 @@
//
// File.swift
//
//
// Created by Nicolas Savoini on 2020-05-25.
//
import Foundation
extension Array where Element == ColorGradient {
@@ -1,10 +1,3 @@
//
// CGRect+Extension.swift
// SwiftUICharts
//
// Created by Nicolas Savoini on 2020-05-24.
//
import Foundation
import SwiftUI
@@ -0,0 +1,10 @@
import SwiftUI
extension View where Self: ChartBase {
public func data(_ data: [Double]) -> some View {
chartData.data = data
return self
.environmentObject(chartData)
.environmentObject(ChartValue())
}
}
@@ -1,11 +1,7 @@
import SwiftUI
extension View {
public func type<S>(_ type: S) -> some View where S: ChartType {
self.environment(\.chartType, AnyChartType(type))
}
public func style(_ style: ChartStyle) -> some View {
self.environment(\.chartStyle, style)
public func chartStyle(_ style: ChartStyle) -> some View {
self.environmentObject(style)
}
}
@@ -1,8 +1,12 @@
import SwiftUI
public struct ChartGrid<Content: View>: View {
public struct ChartGrid<Content: View>: View, ChartBase {
public var chartData = ChartData()
let content: () -> Content
@EnvironmentObject var data: ChartData
@EnvironmentObject var style: ChartStyle
public init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
@@ -4,15 +4,13 @@ public enum ChartLabelType {
case title
case subTitle
case largeTitle
case custom(size: CGFloat)
case custom(size: CGFloat, padding: EdgeInsets, color: Color)
case legend
}
public struct ChartLabel: View {
@Environment(\.chartValue) private var chartValue: ChartValue
@State var textToDisplay = ""
@State var isInteractionInProgress: Bool = false
@EnvironmentObject var chartValue: ChartValue
@State var textToDisplay:String = ""
private var title: String
@@ -26,11 +24,26 @@ public struct ChartLabel: View {
return 24.0
case .largeTitle:
return 38.0
case .custom(let size):
case .custom(let size, _, _):
return size
}
}
private var labelPadding: EdgeInsets {
switch labelType {
case .title:
return EdgeInsets(top: 16.0, leading: 8.0, bottom: 0.0, trailing: 8.0)
case .legend:
return EdgeInsets(top: 4.0, leading: 8.0, bottom: 0.0, trailing: 8.0)
case .subTitle:
return EdgeInsets(top: 8.0, leading: 8.0, bottom: 0.0, trailing: 8.0)
case .largeTitle:
return EdgeInsets(top: 24.0, leading: 8.0, bottom: 0.0, trailing: 8.0)
case .custom(_, let padding, _):
return padding
}
}
private let labelType: ChartLabelType
private var labelColor: Color {
@@ -43,8 +56,8 @@ public struct ChartLabel: View {
return .black
case .largeTitle:
return .black
case .custom(_):
return .black
case .custom(_, _, let color):
return color
}
}
@@ -55,18 +68,21 @@ public struct ChartLabel: View {
}
public var body: some View {
VStack (alignment: self.isInteractionInProgress ? .center : .leading) {
HStack {
Text(textToDisplay)
.font(.system(size: labelSize))
.bold()
.foregroundColor(self.labelColor)
.padding(self.labelPadding)
.onAppear {
self.textToDisplay = title
self.textToDisplay = self.title
}
.onReceive(self.chartValue.objectWillChange) { _ in
self.textToDisplay = self.chartValue.interactionInProgress ? String(format: "%.01f", self.chartValue.currentValue) : self.title
self.isInteractionInProgress = self.chartValue.interactionInProgress
}
if !self.chartValue.interactionInProgress {
Spacer()
}
}
}
}
@@ -1,6 +1,6 @@
import SwiftUI
public struct ChartStyle {
public class ChartStyle: ObservableObject {
public let backgroundColor: ColorGradient
public let foregroundColor: [ColorGradient]
@@ -1,31 +1,14 @@
import SwiftUI
public struct BarChart: ChartType {
public func makeChart(data: Self.Data, style: Self.Style) -> some View {
public struct BarChart: View, ChartBase {
public var chartData = ChartData()
@EnvironmentObject var data: ChartData
@EnvironmentObject var style: ChartStyle
public var body: some View {
BarChartRow(chartData: data, style: style)
}
public init() {}
}
struct BarChart_Previews: PreviewProvider {
static var previews: some View {
Group {
BarChart().makeChart(
data: .init([0]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
Group {
BarChart().makeChart(
data: .init([1, 2, 3, 5, 1]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
}.environment(\.colorScheme, .light)
Group {
BarChart().makeChart(
data: .init([1, 2, 3]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
}.environment(\.colorScheme, .dark)
}
}
}
@@ -1,7 +1,7 @@
import SwiftUI
public struct BarChartRow: View {
@Environment(\.chartValue) private var chartValue: ChartValue
@EnvironmentObject var chartValue: ChartValue
@ObservedObject var chartData: ChartData
@State var touchLocation: CGFloat = -1.0
@@ -39,7 +39,7 @@ public struct BarChartRow: View {
.onChanged({ value in
let width = geometry.frame(in: .local).width
self.touchLocation = value.location.x/width
if let currentValue = getCurrentValue(width: width) {
if let currentValue = self.getCurrentValue(width: width) {
self.chartValue.currentValue = currentValue
self.chartValue.interactionInProgress = true
}
@@ -70,25 +70,3 @@ public struct BarChartRow: View {
return self.chartData.data[index]
}
}
//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])
@@ -1,7 +1,7 @@
import SwiftUI
public struct Line: View {
@Environment(\.chartValue) private var chartValue: ChartValue
@EnvironmentObject var chartValue: ChartValue
@State var frame: CGRect = .zero
@ObservedObject var chartData: ChartData
@@ -91,9 +91,15 @@ extension Line {
private func getBackgroundPathView() -> some View {
self.closedPath
.fill(style.backgroundColor.linearGradient(from: .bottom, to: .top))
.fill(LinearGradient(gradient: Gradient(colors: [
style.foregroundColor.first?.startColor ?? .white,
style.foregroundColor.first?.endColor ?? .white,
.white]),
startPoint: .bottom,
endPoint: .top))
.rotationEffect(.degrees(180), anchor: .center)
.rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0))
.opacity(0.2)
.transition(.opacity)
.animation(.easeIn(duration: 1.6))
}
@@ -1,32 +1,14 @@
import SwiftUI
public struct LineChart: ChartType {
public func makeChart(data: Self.Data, style: Self.Style) -> some View {
public struct LineChart: View, ChartBase {
public var chartData = ChartData()
@EnvironmentObject var data: ChartData
@EnvironmentObject var style: ChartStyle
public var body: some View {
Line(chartData: data, style: style)
}
public init() {}
}
struct LineChart_Previews: PreviewProvider {
static var previews: some View {
Group {
LineChart().makeChart(
data: .init([0]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient(.black)))
Group {
LineChart().makeChart(
data: .init([1, 2, 3, 5, 1]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient(.black)))
}.environment(\.colorScheme, .light)
Group {
LineChart().makeChart(
data: .init([1, 2, 3]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
}.environment(\.colorScheme, .dark)
}
}
}
@@ -1,63 +1,14 @@
//
// PieChart.swift
// SwiftUICharts
//
// Created by Nicolas Savoini on 2020-05-24.
//
import SwiftUI
public struct PieChart: ChartType {
public func makeChart(data: Self.Data, style: Self.Style) -> some View {
public struct PieChart: View, ChartBase {
public var chartData = ChartData()
@EnvironmentObject var data: ChartData
@EnvironmentObject var style: ChartStyle
public var body: some View {
PieChartRow(chartData: data, style: style)
}
public init() {}
}
struct PieChart_Previews: PreviewProvider {
static var previews: some View {
Group {
PieChart().makeChart(
data: .init([0]),
style: styleOneColor)
Group {
PieChart().makeChart(
data: .init([56, 78, 53, 65, 54]),
style: styleOneColor)
PieChart().makeChart(
data: .init([56, 78, 53, 65, 54]),
style: styleTwoColor)
PieChart().makeChart(
data: .init([1, 1, 1, 1, 1, 1]),
style: trivialPursuit)
}.environment(\.colorScheme, .light)
Group {
PieChart().makeChart(
data: .init([56, 78, 53, 65, 54]),
style: styleOneColor)
PieChart().makeChart(
data: .init([56, 78, 53, 65, 54]),
style: styleTwoColor)
PieChart().makeChart(
data: .init([1, 1, 1, 1, 1, 1]),
style: trivialPursuit)
}.environment(\.colorScheme, .dark)
}.previewLayout(.fixed(width: 250, height: 400))
}
}
private let styleOneColor = ChartStyle(backgroundColor: .white, foregroundColor: ColorGradient.init(.pink))
private let styleTwoColor = ChartStyle(backgroundColor: ColorGradient(.black), foregroundColor: [ColorGradient(.yellow), ColorGradient(.red)])
private let trivialPursuit = ChartStyle(
backgroundColor: .yellow,
foregroundColor: [ColorGradient(.yellow),
ColorGradient(.pink),
ColorGradient(.green),
ColorGradient(.primary),
ColorGradient(.blue),
ColorGradient(.orange)])
@@ -1,30 +0,0 @@
import SwiftUI
extension EnvironmentValues {
var chartType: AnyChartType {
get {
return self[ChartTypeKey.self]
}
set {
self[ChartTypeKey.self] = newValue
}
}
var chartStyle: ChartStyle {
get {
return self[ChartStyleKey.self]
}
set {
self[ChartStyleKey.self] = newValue
}
}
var chartValue: ChartValue {
get {
return self[ChartValueKey.self]
}
set {
self[ChartValueKey.self] = newValue
}
}
}
@@ -1,15 +0,0 @@
import SwiftUI
struct ChartTypeKey: EnvironmentKey {
static let defaultValue: AnyChartType = AnyChartType(BarChart())
}
struct ChartStyleKey: EnvironmentKey {
static let defaultValue: ChartStyle = ChartStyle(backgroundColor: .white,
foregroundColor: ColorGradient(ChartColors.orangeDark,
ChartColors.orangeBright))
}
struct ChartValueKey: EnvironmentKey {
static let defaultValue: ChartValue = ChartValue()
}