Compare commits

...

9 Commits

Author SHA1 Message Date
Andras Samu e5c309eac4 set to public 2019-11-11 20:41:42 +01:00
Andras Samu 3f542f92e3 Added LineView 2019-11-11 20:29:41 +01:00
sy1995 7a9f013631 Hi, I find that the LineChartView has a value is static (#15)
* add rateValue to LineChart

* modify

* modify rate value to linechart

* modify

* modify
2019-11-11 15:58:21 +01:00
Andras Samu 8dffe79e28 Merge pull request #10 from jufabeck2202/Uint64
'scanHexInt32' was deprecated in iOS 13.0
2019-10-15 09:40:19 +02:00
Julian Beck d5a1c0065c 'scanHexInt32' was deprecated in iOS 13.0 2019-10-10 21:52:21 +02:00
Andras Samu b9761d3eb9 Update README.md 2019-10-07 10:51:25 +02:00
Andras Samu c3c0a8a7c4 Merge pull request #8 from WayneEld/issue/print-line-removed
Removal of index print line.
2019-10-04 11:46:05 +02:00
Wayne Eldridge b597faac76 Removal of index print line. 2019-10-03 20:02:42 +02:00
Andras Samu fc1099f486 Update README.md 2019-09-30 20:45:32 +02:00
7 changed files with 156 additions and 13 deletions
+5 -1
View File
@@ -21,6 +21,10 @@ 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:
### Demo
Added an example project, with **iOS, watchOS** target: https://github.com/AppPear/ChartViewDemo
## Line charts
![Line Charts](./showcase3.gif "Line Charts")
@@ -50,7 +54,7 @@ You can add different formats:
* Large `Form.large`
```swift
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", style: ChartStyle(formSize: Form.small))
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", form: Form.small)
```
### You can customize styling of the chart with a ChartStyle object:
@@ -14,6 +14,8 @@ public struct BarChartView : View {
public var legend: String?
public var style: ChartStyle
public var formSize:CGSize
public var dropShadow: Bool
// let selectionFeedbackGenerator = UISelectionFeedbackGenerator()
@State private var touchLocation: CGFloat = -1.0
@@ -29,12 +31,13 @@ public struct BarChartView : View {
var isFullWidth:Bool {
return self.formSize == Form.large
}
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.barChartStyleOrangeLight, form: CGSize? = Form.medium){
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.barChartStyleOrangeLight, form: CGSize? = Form.medium, dropShadow: Bool? = true){
self.data = data
self.title = title
self.legend = legend
self.style = style
self.formSize = form!
self.dropShadow = dropShadow!
}
public var body: some View {
@@ -42,7 +45,7 @@ public struct BarChartView : View {
Rectangle()
.fill(self.style.backgroundColor)
.cornerRadius(20)
.shadow(color: Color.gray, radius: 8 )
.shadow(color: Color.gray, radius: self.dropShadow ? 8 : 0)
VStack(alignment: .leading){
HStack{
if(!showValue){
@@ -93,7 +96,6 @@ public struct BarChartView : View {
func getCurrentValue()-> Int{
let index = max(0,min(self.data.count-1,Int(floor((self.touchLocation*self.formSize.width)/(self.formSize.width/CGFloat(self.data.count))))))
print(index)
return self.data[index]
}
}
+3 -3
View File
@@ -143,9 +143,9 @@ class TestData{
extension Color {
init(hexString: String) {
let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int = UInt32()
Scanner(string: hex).scanHexInt32(&int)
let r, g, b: UInt32
var int = UInt64()
Scanner(string: hex).scanHexInt64(&int)
let r, g, b: UInt64
switch hex.count {
case 3: // RGB (12-bit)
(r, g, b) = ((int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
@@ -15,6 +15,8 @@ public struct LineChartView: View {
public var legend: String?
public var style: ChartStyle
public var formSize:CGSize
public var dropShadow: Bool
@State private var touchLocation:CGPoint = .zero
@State private var showIndicatorDot: Bool = false
@State private var currentValue: Int = 2 {
@@ -27,18 +29,21 @@ public struct LineChartView: View {
}
}
let frame = CGSize(width: 180, height: 120)
private var rateValue: Int
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.lineChartStyleOne, form: CGSize? = Form.medium){
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.lineChartStyleOne, form: CGSize? = Form.medium ,rateValue: Int? = 14, dropShadow: Bool? = true){
self.data = ChartData(points: data)
self.title = title
self.legend = legend
self.style = style
self.formSize = form!
self.rateValue = rateValue!
self.dropShadow = dropShadow!
}
public var body: some View {
ZStack(alignment: .center){
RoundedRectangle(cornerRadius: 20).fill(self.style.backgroundColor).frame(width: frame.width, height: 240, alignment: .center).shadow(radius: 8)
RoundedRectangle(cornerRadius: 20).fill(self.style.backgroundColor).frame(width: frame.width, height: 240, alignment: .center).shadow(radius: self.dropShadow ? 8 : 0)
VStack(alignment: .leading){
if(!self.showIndicatorDot){
VStack(alignment: .leading, spacing: 8){
@@ -47,8 +52,12 @@ public struct LineChartView: View {
Text(self.legend!).font(.callout).foregroundColor(self.style.legendTextColor)
}
HStack {
Image(systemName: "arrow.up")
Text("14%")
if (self.rateValue >= 0){
Image(systemName: "arrow.up")
}else{
Image(systemName: "arrow.down")
}
Text("\(self.rateValue)%")
}
}
.transition(.opacity)
@@ -0,0 +1,125 @@
//
// LineView.swift
// LineChart
//
// Created by András Samu on 2019. 09. 02..
// Copyright © 2019. András Samu. All rights reserved.
//
import SwiftUI
public struct LineView: View {
@ObservedObject var data: ChartData
public var title: String?
public var legend: String?
public var style: ChartStyle
@Environment(\.colorScheme) var colorScheme: ColorScheme
@State private var showLegend = false
@State private var dragLocation:CGPoint = .zero
@State private var indicatorLocation:CGPoint = .zero
@State private var closestPoint: CGPoint = .zero
@State private var opacity:Double = 0
@State private var currentDataNumber: Int = 0
@State private var hideHorizontalLines: Bool = false
public init(data: [Int], title: String? = nil, legend: String? = nil, style: ChartStyle? = Styles.lineChartStyleOne){
self.data = ChartData(points: data)
self.title = title
self.legend = legend
self.style = style!
}
public var body: some View {
GeometryReader{ geometry in
VStack(alignment: .leading, spacing: 8) {
Group{
if (self.title != nil){
Text(self.title!).font(.title).bold().foregroundColor(self.colorScheme == .dark ? Color.white : self.style.textColor)
}
if (self.legend != nil){
Text(self.legend!).font(.callout).foregroundColor(self.colorScheme == .dark ? Color.white : self.style.legendTextColor)
}
}.offset(x: 0, y: 46)
ZStack{
GeometryReader{ reader in
Rectangle().foregroundColor(self.colorScheme == .dark ? Color.black : self.style.backgroundColor)
if(self.showLegend){
Legend(data: self.data, frame: .constant(reader.frame(in: .local)), hideHorizontalLines: self.$hideHorizontalLines)
.transition(.opacity)
.animation(Animation.easeOut(duration: 1).delay(1))
}
Line(data: self.data, frame: .constant(CGRect(x: 0, y: 0, width: reader.frame(in: .local).width - 30, height: reader.frame(in: .local).height)), touchLocation: self.$indicatorLocation,showIndicator: self.$hideHorizontalLines ,showBackground: false).offset(x: 30, y: 0)
.onAppear(){
self.showLegend.toggle()
}
}.frame(width: geometry.frame(in: .local).size.width, height: 240).offset(x: 0, y: 40 )
MagnifierRect(currentNumber: self.$currentDataNumber)
.opacity(self.opacity)
.offset(x: self.dragLocation.x - geometry.frame(in: .local).size.width/2, y: 50)
}
.frame(width: geometry.frame(in: .local).size.width, height: 240)
.gesture(DragGesture()
.onChanged({ value in
self.dragLocation = value.location
self.indicatorLocation = CGPoint(x: max(value.location.x-30,0), y: 32)
self.opacity = 1
self.closestPoint = self.getClosestDataPoint(toPoint: value.location, width: geometry.frame(in: .local).size.width-30, height: 240)
self.hideHorizontalLines = true
})
.onEnded({ value in
self.opacity = 0
self.hideHorizontalLines = false
})
)
}
}
}
func getClosestDataPoint(toPoint: CGPoint, width:CGFloat, height: CGFloat) -> CGPoint {
let stepWidth: CGFloat = width / CGFloat(data.points.count-1)
let stepHeight: CGFloat = height / CGFloat(data.points.max()! + data.points.min()!)
let index:Int = Int(floor((toPoint.x-15)/stepWidth))
if (index >= 0 && index < data.points.count){
self.currentDataNumber = self.data.points[index]
return CGPoint(x: CGFloat(index)*stepWidth, y: CGFloat(self.data.points[index])*stepHeight)
}
return .zero
}
}
struct LineView_Previews: PreviewProvider {
static var previews: some View {
LineView(data: [37,72,51,22,39,47,66,85,50], title: "Full chart", style: Styles.lineChartStyleOne).environment(\.colorScheme, .dark)
}
}
struct IndicatorCircle: View {
var body: some View {
Circle()
.size(width: 12, height: 12)
.fill(Colors.BorderBlue)
}
}
struct MagnifierRect: View {
@Binding var currentNumber:Int
@Environment(\.colorScheme) var colorScheme: ColorScheme
var body: some View {
ZStack{
Text("\(self.currentNumber)")
.font(.system(size: 18, weight: .bold))
.offset(x: 0, y:-96)
.animation(.spring())
.foregroundColor(self.colorScheme == .dark ? Color.white : Color.black)
RoundedRectangle(cornerRadius: 16)
.stroke(Color.white, lineWidth: self.colorScheme == .dark ? 2 : 0)
.frame(width: 60, height: 240)
.foregroundColor(self.colorScheme == .dark ? Color.black : Color.white)
.shadow(color: Colors.LegendText, radius: 12, x: 0, y: 6 )
.blendMode(self.colorScheme == .dark ? .normal : .multiply)
}.animation(.linear)
}
}
@@ -14,12 +14,15 @@ public struct PieChartView : View {
public var legend: String?
public var style: ChartStyle
public var formSize:CGSize
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.pieChartStyleOne, form: CGSize? = Form.medium ){
public var dropShadow: Bool
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.pieChartStyleOne, form: CGSize? = Form.medium, dropShadow: Bool? = true ){
self.data = data
self.title = title
self.legend = legend
self.style = style
self.formSize = form!
self.dropShadow = dropShadow!
}
public var body: some View {
@@ -27,7 +30,7 @@ public struct PieChartView : View {
Rectangle()
.fill(self.style.backgroundColor)
.cornerRadius(20)
.shadow(color: Color.gray, radius: 12)
.shadow(color: Color.gray, radius: self.dropShadow ? 12 : 0)
VStack(alignment: .leading){
HStack{
Text(self.title)