Skip to content

Commit

Permalink
Add PieChart + multicolor (#98)
Browse files Browse the repository at this point in the history
* Add ColorGradient example
Add ColorGradient single color constructor
Add preview for BarChart

* Add PieChart
Allow multi color for Pie and Bar
Add linter
  • Loading branch information
satan87 authored May 25, 2020
1 parent a2d75dc commit aa91264
Show file tree
Hide file tree
Showing 14 changed files with 472 additions and 27 deletions.
64 changes: 64 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
disabled_rules:
- explicit_acl
- trailing_whitespace
- force_cast
- unused_closure_parameter
- multiple_closures_with_trailing_closure
opt_in_rules:
- anyobject_protocol
- array_init
- attributes
- collection_alignment
- colon
- conditional_returns_on_newline
- convenience_type
- empty_count
- empty_string
- empty_collection_literal
- enum_case_associated_values_count
- function_default_parameter_at_end
- fatal_error_message
- file_name
- first_where
- modifier_order
- toggle_bool
- unused_private_declaration
- yoda_condition
excluded:
- Carthage
- Pods
- SwiftLint/Common/3rdPartyLib
identifier_name:
excluded:
- a
- b
- c
- i
- id
- t
- to
- x
- y
line_length:
warning: 150
error: 200
ignores_function_declarations: true
ignores_comments: true
ignores_urls: true
function_body_length:
warning: 300
error: 500
function_parameter_count:
warning: 6
error: 8
type_body_length:
warning: 300
error: 400
file_length:
warning: 500
error: 1200
ignore_comment_only_lines: true
cyclomatic_complexity:
warning: 15
error: 21
reporter: "xcode"
6 changes: 3 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import PackageDescription
let package = Package(
name: "SwiftUICharts",
platforms: [
.iOS(.v13),.watchOS(.v6)
.iOS(.v13), .watchOS(.v6)
],
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "SwiftUICharts",
targets: ["SwiftUICharts"]),
targets: ["SwiftUICharts"])
],
dependencies: [
// Dependencies declare other packages that this package depends on.
Expand All @@ -26,6 +26,6 @@ let package = Package(
dependencies: []),
.testTarget(
name: "SwiftUIChartsTests",
dependencies: ["SwiftUICharts"]),
dependencies: ["SwiftUICharts"])
]
)
16 changes: 16 additions & 0 deletions Sources/SwiftUICharts/Base/Extensions/CGRect+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// CGRect+Extension.swift
// SwiftUICharts
//
// Created by Nicolas Savoini on 2020-05-24.
//

import Foundation
import SwiftUI

extension CGRect {
// Return the coordinate for a rectangle center
public var mid: CGPoint {
return CGPoint(x: self.midX, y: self.midY)
}
}
12 changes: 6 additions & 6 deletions Sources/SwiftUICharts/Base/Extensions/Color+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ extension Color {
let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int = UInt64()
Scanner(string: hex).scanHexInt64(&int)
let r, g, b: UInt64
let red, green, blue: UInt64
switch hex.count {
case 3: // RGB (12-bit)
(r, g, b) = ((int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
(red, green, blue) = ((int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
case 6: // RGB (24-bit)
(r, g, b) = (int >> 16, int >> 8 & 0xFF, int & 0xFF)
(red, green, blue) = (int >> 16, int >> 8 & 0xFF, int & 0xFF)
case 8: // ARGB (32-bit)
(r, g, b) = (int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
(red, green, blue) = (int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
default:
(r, g, b) = (0, 0, 0)
(red, green, blue) = (0, 0, 0)
}
self.init(red: Double(r) / 255, green: Double(g) / 255, blue: Double(b) / 255)
self.init(red: Double(red) / 255, green: Double(green) / 255, blue: Double(blue) / 255)
}
}
21 changes: 19 additions & 2 deletions Sources/SwiftUICharts/Base/Style/ChartStyle.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
import SwiftUI

public struct ChartStyle {
public let backgroundColor: Color
public let foregroundColor: ColorGradient

public let backgroundColor: ColorGradient
public let foregroundColor: [ColorGradient]

public init(backgroundColor: Color, foregroundColor: [ColorGradient]) {
self.backgroundColor = ColorGradient.init(backgroundColor)
self.foregroundColor = foregroundColor
}

public init(backgroundColor: Color, foregroundColor: ColorGradient) {
self.backgroundColor = ColorGradient.init(backgroundColor)
self.foregroundColor = [foregroundColor]
}

public init(backgroundColor: ColorGradient, foregroundColor: ColorGradient) {
self.backgroundColor = backgroundColor
self.foregroundColor = [foregroundColor]
}

public init(backgroundColor: ColorGradient, foregroundColor: [ColorGradient]) {
self.backgroundColor = backgroundColor
self.foregroundColor = foregroundColor
}

}
23 changes: 23 additions & 0 deletions Sources/SwiftUICharts/Base/Style/ColorGradient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ public struct ColorGradient {
public let startColor: Color
public let endColor: Color

public init(_ color: Color) {
self.startColor = color
self.endColor = color
}

public init (_ startColor: Color, _ endColor: Color) {
self.startColor = startColor
self.endColor = endColor
Expand All @@ -13,3 +18,21 @@ public struct ColorGradient {
return Gradient(colors: [startColor, endColor])
}
}

extension ColorGradient {
/// Convenience method to return a LinearGradient from the ColorGradient
/// - Parameters:
/// - startPoint: starting point
/// - endPoint: ending point
/// - Returns: a Linear gradient
public func linearGradient(from startPoint: UnitPoint, to endPoint: UnitPoint) -> LinearGradient {
return LinearGradient(gradient: self.gradient, startPoint: startPoint, endPoint: endPoint)
}
}

extension ColorGradient {
public static let orangeBright = ColorGradient(ChartColors.orangeBright)
public static let redBlack = ColorGradient(.red, .black)
public static let greenRed = ColorGradient(.green, .red)
public static let whiteBlack = ColorGradient(.white, .black)
}
22 changes: 20 additions & 2 deletions Sources/SwiftUICharts/Charts/BarChart/BarChart.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,26 @@ import SwiftUI

public struct BarChart: ChartType {
public func makeChart(configuration: Self.Configuration, style: Self.Style) -> some View {
BarChartRow(data: configuration.data, gradientColor: style.foregroundColor)
BarChartRow(data: configuration.data, style: style)
}

public init() {}
}

struct BarChart_Previews: PreviewProvider {
static var previews: some View {
Group {
Group {
BarChart().makeChart(
configuration: .init(data: [1, 2, 3, 5, 1]),
style: .init(backgroundColor: .white, foregroundColor: ColorGradient.redBlack))
}.environment(\.colorScheme, .light)

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

}
}
}
26 changes: 23 additions & 3 deletions Sources/SwiftUICharts/Charts/BarChart/BarChartCell.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import SwiftUI

public struct BarChartCell : View {
public struct BarChartCell: View {
@State var value: Double
@State var index: Int = 0
@State var width: Float
Expand All @@ -13,16 +13,36 @@ public struct BarChartCell : View {

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

public var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 4)
.fill(LinearGradient(gradient: gradientColor.gradient, startPoint: .bottom, endPoint: .top))
.fill(gradientColor.linearGradient(from: .bottom, to: .top))
}
.frame(width: CGFloat(self.cellWidth))
.scaleEffect(CGSize(width: 1, height: self.scaleValue), anchor: .bottom)
.onAppear(){
.onAppear {
self.scaleValue = self.value
}
.animation(Animation.spring().delay(self.touchLocation < 0 ? Double(self.index) * 0.04 : 0))
}
}

struct BarChartCell_Previews: PreviewProvider {
static var previews: some View {
Group {
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()))
}

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()))
}.environment(\.colorScheme, .dark)
}

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

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

enum Constant {
static let spacing: CGFloat = 16.0
}

var gradientColor: ColorGradient
var style: ChartStyle

var maxValue: Double {
data.max() ?? 0
}
Expand All @@ -17,14 +18,14 @@ public struct BarChartRow : 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) { i in
BarChartCell(value: self.normalizedValue(index: i),
index: i,
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.gradientColor,
gradientColor: self.style.foregroundColor.rotate(for: index),
touchLocation: self.$touchLocation)
.scaleEffect(self.getScaleSize(touchLocation: self.touchLocation, index: i), anchor: .bottom)
.scaleEffect(self.getScaleSize(touchLocation: self.touchLocation, index: index), anchor: .bottom)
.animation(.spring())

}
Expand Down Expand Up @@ -52,4 +53,26 @@ public struct BarChartRow : View {
}
return CGSize(width: 1, height: 1)
}

}

struct BarChartRow_Previews: PreviewProvider {
static var previews: some View {
Group {
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])
18 changes: 15 additions & 3 deletions Sources/SwiftUICharts/Charts/LineChart/Line.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SwiftUI
public struct Line: View {
@State var frame: CGRect = .zero
@State var data: [Double]
var gradientColor: ColorGradient
var style: ChartStyle

@State var showIndicator: Bool = false
@State var touchLocation: CGPoint = .zero
Expand Down Expand Up @@ -79,7 +79,7 @@ extension Line {

private func getBackgroundPathView() -> some View {
self.closedPath
.fill(LinearGradient(gradient: gradientColor.gradient, startPoint: .bottom, endPoint: .top))
.fill(style.backgroundColor.linearGradient(from: .bottom, to: .top))
.rotationEffect(.degrees(180), anchor: .center)
.rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0))
.transition(.opacity)
Expand All @@ -89,7 +89,7 @@ extension Line {
private func getLinePathView() -> some View {
self.path
.trim(from: 0, to: self.showFull ? 1:0)
.stroke(LinearGradient(gradient: gradientColor.gradient,
.stroke(LinearGradient(gradient: style.foregroundColor.first?.gradient ?? ColorGradient.orangeBright.gradient,
startPoint: .leading,
endPoint: .trailing),
style: StrokeStyle(lineWidth: 3, lineJoin: .round))
Expand All @@ -105,3 +105,15 @@ extension Line {
.drawingGroup()
}
}

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)
}
}
}

private let blackLineStyle = ChartStyle(backgroundColor: ColorGradient(.white), foregroundColor: ColorGradient(.black))
private let redLineStyle = ChartStyle(backgroundColor: .whiteBlack, foregroundColor: ColorGradient(.red))
Loading

0 comments on commit aa91264

Please sign in to comment.