Skip to content

Commit

Permalink
Added new interactive Bar chart
Browse files Browse the repository at this point in the history
Added new Line chart (also interactive)
Added new color schemes
  • Loading branch information
AppPear committed Sep 11, 2019
1 parent d668225 commit 8197fd6
Show file tree
Hide file tree
Showing 23 changed files with 723 additions and 191 deletions.
Binary file not shown.
72 changes: 48 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

Swift package for displaying charts effortlessly.

![SwiftUI Charts](./chartview.gif "SwiftUI Charts")
![SwiftUI Charts](./showcase1.gif "SwiftUI Charts")

It supports currently:
* barcharts
* piecharts
It supports:
* Line charts
* Bar charts
* Pie charts

### Installation:

Expand All @@ -20,40 +21,63 @@ import the package in the file you would like to use it: `import SwiftUICharts`

You can display a Chart by adding a chart view to your parent view:

Barchart:
## Line charts
![Line Charts](./showcase3.gif "Line Charts")

**Line chart is interactive, so you can drag across to reveal the data points**

You can add a line chart with the following code:

```swift
ChartView(data: [8,23,54,32,12,37,7,23,43], title: "Barchart")
LineChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", legend: "Legendary") // legend is optional
```

Piechart:

## Bar charts
![Bar Charts](./showcase2.gif "Bar Charts")

**Bar chart is interactive, so you can drag across to reveal the data points**

You can add a bar chart with the following code:

```swift
PieChartView(data:[43,56,78,34], title: "Piechart")
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", legend: "Legendary") // legend is optional
```

You can optionally configure:
* legend
You can add different formats:
* Small `Form.small`
* Medium `Form.medium`
* Large `Form.large`

```swift
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", style: ChartStyle(formSize: Form.small))
```

### You can customize styling of the chart with a ChartStyle object:

Customizable:
* background color
* accent color
* size format
* second gradient color
* chart form size
* text color
* legend text color

### Size format (only for bar charts yet!)
```swift
let chartStyle = ChartStyle(backgroundColor: Color.black, accentColor: Colors.OrangeStart, secondGradientColor: Colors.OrangeEnd, chartFormSize: Form.medium, textColor: Color.white, legendTextColor: Color.white )
...
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", style: chartStyle)
```

![Chart forms](./chartforms.png "Chart forms")
![Custom Charts](./showcase5.png "Custom Charts")

Can be
* small
* medium
* large

```swift
ChartView(data: [12,17,24,33,23,56], title: "Chart two", form: Form.small)
```
## Pie charts
![Pie Charts](./showcase4.png "Pie Charts")

### Customizing color:
I added color constants, so you can predefine your color palette. To do so, you can find `Colors` struct in the ChartColors swift file.
You can add a line chart with the following code:

```swift
ChartView(data: [12,17,24,33,23,56], title: "Chart two", backgroundColor:Colors.color3 , accentColor:Colors.color3Accent)
PieChartView(data: [8,23,54,32], title: "Title", legend: "Legendary") // legend is optional
```


Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,42 @@

import SwiftUI

public struct ChartCell : View {
public struct BarChartCell : View {
var value: Double
var index: Int = 0
var width: Float
var numberOfDataPoints: Int
var cellWidth: Double {
return Double(width)/(Double(numberOfDataPoints) * 1.5)
}
var accentColor: Color
var secondGradientAccentColor: Color?
var gradientColors:[Color] {
if (secondGradientAccentColor != nil) {
return [secondGradientAccentColor!, accentColor]
}
return [accentColor, accentColor]
}
@State var scaleValue: Double = 0
@Binding var touchLocation: CGFloat
public var body: some View {
ZStack {
Rectangle()
.cornerRadius(4)
RoundedRectangle(cornerRadius: 4)
.fill(LinearGradient(gradient: Gradient(colors: gradientColors), startPoint: .bottom, endPoint: .top))
}
.frame(width: CGFloat(self.cellWidth))
.scaleEffect(CGSize(width: 1, height: self.scaleValue), anchor: .bottom)
.onAppear(){
self.scaleValue = self.value
}
.animation(Animation.spring().delay(Double(self.index) * 0.04))
.animation(Animation.spring().delay(self.touchLocation < 0 ? Double(self.index) * 0.04 : 0))
}
}

#if DEBUG
struct ChartCell_Previews : PreviewProvider {
static var previews: some View {
ChartCell(value: Double(0.75), width: 320, numberOfDataPoints: 12)
BarChartCell(value: Double(0.75), width: 320, numberOfDataPoints: 12, accentColor: Colors.OrangeStart, secondGradientAccentColor: nil, touchLocation: .constant(-1))
}
}
#endif
39 changes: 39 additions & 0 deletions Sources/SwiftUICharts/BarChart/BarChartRow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// ChartRow.swift
// ChartView
//
// Created by András Samu on 2019. 06. 12..
// Copyright © 2019. András Samu. All rights reserved.
//

import SwiftUI

public struct BarChartRow : View {
var data: [Int]
var accentColor: Color
var secondGradientAccentColor: Color?
var maxValue: Int {
data.max() ?? 0
}
@Binding var touchLocation: CGFloat
public var body: some View {
GeometryReader { geometry in
HStack(alignment: .bottom, spacing: (geometry.frame(in: .local).width-22)/CGFloat(self.data.count * 3)){
ForEach(0..<self.data.count) { i in
BarChartCell(value: Double(self.data[i])/Double(self.maxValue), index: i, width: Float(geometry.frame(in: .local).width - 22), numberOfDataPoints: self.data.count, accentColor: self.accentColor, secondGradientAccentColor: self.secondGradientAccentColor, touchLocation: self.$touchLocation)
.scaleEffect(self.touchLocation > CGFloat(i)/CGFloat(self.data.count) && self.touchLocation < CGFloat(i+1)/CGFloat(self.data.count) ? CGSize(width: 1.4, height: 1.1) : CGSize(width: 1, height: 1), anchor: .bottom)

}
}
.padding([.top, .leading, .trailing], 10)
}
}
}

#if DEBUG
struct ChartRow_Previews : PreviewProvider {
static var previews: some View {
BarChartRow(data: [8,23,54,32,12,37,7], accentColor: Colors.OrangeStart, touchLocation: .constant(-1))
}
}
#endif
104 changes: 104 additions & 0 deletions Sources/SwiftUICharts/BarChart/BarChartView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//
// ChartView.swift
// ChartView
//
// Created by András Samu on 2019. 06. 12..
// Copyright © 2019. András Samu. All rights reserved.
//

import SwiftUI

public struct BarChartView : View {
public var data: [Int]
public var title: String
public var legend: String?
public var style: ChartStyle
let selectionFeedbackGenerator = UISelectionFeedbackGenerator()

@State private var touchLocation: CGFloat = -1.0
@State private var showValue: Bool = false
@State private var currentValue: Int = 0 {
didSet{
if(oldValue != self.currentValue && self.showValue) {
selectionFeedbackGenerator.selectionChanged()
}
}
}
var isFullWidth:Bool {
return self.style.chartFormSize == Form.large
}
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.barChartStyleOne ){
self.data = data
self.title = title
self.legend = legend
self.style = style
}

public var body: some View {
ZStack{
Rectangle()
.fill(self.style.backgroundColor)
.cornerRadius(20)
.shadow(color: Color.gray, radius: 8 )
VStack(alignment: .leading){
HStack{
if(!showValue){
Text(self.title)
.font(.headline)
.foregroundColor(self.style.textColor)
}else{
Text("\(self.currentValue)")
.font(.headline)
.foregroundColor(self.style.textColor)
}
if(self.style.chartFormSize == Form.large && self.legend != nil && !showValue) {
Text(self.legend!)
.font(.callout)
.foregroundColor(self.style.accentColor)
.transition(.opacity)
.animation(.easeOut)
}
Spacer()
Image(systemName: "waveform.path.ecg")
.imageScale(.large)
.foregroundColor(self.style.legendTextColor)
}.padding()
BarChartRow(data: data, accentColor: self.style.accentColor, secondGradientAccentColor: self.style.secondGradientColor, touchLocation: self.$touchLocation)
if self.legend != nil && self.style.chartFormSize == Form.medium {
Text(self.legend!)
.font(.headline)
.foregroundColor(self.style.legendTextColor)
.padding()
}

}
}.frame(minWidth:self.style.chartFormSize.width, maxWidth: self.isFullWidth ? .infinity : self.style.chartFormSize.width, minHeight:self.style.chartFormSize.height, maxHeight:self.style.chartFormSize.height)
.gesture(DragGesture()
.onChanged({ value in
self.touchLocation = value.location.x/self.style.chartFormSize.width
self.showValue = true
self.currentValue = self.getCurrentValue()
})
.onEnded({ value in
self.showValue = false
self.touchLocation = -1
})
)
.gesture(TapGesture()
)
}

func getCurrentValue()-> Int{
let index = max(0,min(self.data.count-1,Int(floor((self.touchLocation*self.style.chartFormSize.width)/(self.style.chartFormSize.width/CGFloat(self.data.count))))))
print(index)
return self.data[index]
}
}

#if DEBUG
struct ChartView_Previews : PreviewProvider {
static var previews: some View {
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", legend: "Legendary")
}
}
#endif
38 changes: 0 additions & 38 deletions Sources/SwiftUICharts/ChartColors.swift

This file was deleted.

34 changes: 0 additions & 34 deletions Sources/SwiftUICharts/ChartRow.swift

This file was deleted.

Loading

0 comments on commit 8197fd6

Please sign in to comment.