Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3265d3e16b | |||
| c46902dab8 |
@@ -1,20 +1,25 @@
|
||||
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
|
||||
|
||||
public init(@ViewBuilder content: @escaping () -> Content) {
|
||||
private var showShadow: Bool
|
||||
|
||||
@EnvironmentObject var style: ChartStyle
|
||||
|
||||
public init(showShadow: Bool = true, @ViewBuilder content: @escaping () -> Content) {
|
||||
self.showShadow = showShadow
|
||||
self.content = content
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
ZStack{
|
||||
Rectangle()
|
||||
.fill(Color.white)
|
||||
.cornerRadius(20)
|
||||
.shadow(color: Color.gray, radius: 8)
|
||||
if showShadow {
|
||||
RoundedRectangle(cornerRadius: 20)
|
||||
.fill(Color.white)
|
||||
.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]
|
||||
|
||||
@@ -2,9 +2,9 @@ import SwiftUI
|
||||
|
||||
public enum ChartColors {
|
||||
// Orange
|
||||
static let orangeBright = Color(hexString: "#FF782C")
|
||||
static let orangeDark = Color(hexString: "#EC2301")
|
||||
public static let orangeBright = Color(hexString: "#FF782C")
|
||||
public static let orangeDark = Color(hexString: "#EC2301")
|
||||
|
||||
static let legendColor: Color = Color(hexString: "#E8E7EA")
|
||||
static let indicatorKnob: Color = Color(hexString: "#FF57A6")
|
||||
public static let legendColor: Color = Color(hexString: "#E8E7EA")
|
||||
public static let indicatorKnob: Color = Color(hexString: "#FF57A6")
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
Reference in New Issue
Block a user