Compare commits
19 Commits
1.2.0-beta
...
1.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f542f92e3 | |||
| 7a9f013631 | |||
| 8dffe79e28 | |||
| d5a1c0065c | |||
| b9761d3eb9 | |||
| c3c0a8a7c4 | |||
| b597faac76 | |||
| fc1099f486 | |||
| 94950db4d5 | |||
| 251a830281 | |||
| b2b0b83b4b | |||
| 94a98ee2c7 | |||
| da015797dd | |||
| 617297cbcd | |||
| 3909818a3f | |||
| df24b3d1c2 | |||
| 07a16d5548 | |||
| 4512fd0d3e | |||
| 8a54155e47 |
Generated
BIN
Binary file not shown.
+1
-1
@@ -6,7 +6,7 @@ import PackageDescription
|
||||
let package = Package(
|
||||
name: "SwiftUICharts",
|
||||
platforms: [
|
||||
.iOS(.v13),
|
||||
.iOS(.v13),.watchOS(.v6)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries produced by a package, and make them visible to other packages.
|
||||
|
||||
@@ -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
|
||||

|
||||
|
||||
@@ -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:
|
||||
@@ -59,7 +63,6 @@ Customizable:
|
||||
* background color
|
||||
* accent color
|
||||
* second gradient color
|
||||
* chart form size
|
||||
* text color
|
||||
* legend text color
|
||||
|
||||
@@ -69,9 +72,39 @@ Customizable:
|
||||
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", style: chartStyle)
|
||||
```
|
||||
|
||||
You can access built-in styles:
|
||||
```swift
|
||||
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", style: Styles.barChartMidnightGreen)
|
||||
```
|
||||
#### All styles available as a preset:
|
||||
* barChartStyleOrangeLight
|
||||
* barChartStyleOrangeDark
|
||||
* barChartStyleNeonBlueLight
|
||||
* barChartStyleNeonBlueDark
|
||||
* barChartMidnightGreenLight
|
||||
* barChartMidnightGreenDark
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
### You can customize the size of the chart with a Form object:
|
||||
|
||||
**Form**
|
||||
* `.small`
|
||||
* `.medium`
|
||||
* `.large`
|
||||
* `.detail`
|
||||
|
||||
```swift
|
||||
BarChartView(data: [8,23,54,32,12,37,7,23,43], title: "Title", form: Form.small)
|
||||
```
|
||||
|
||||
### WatchOS support for Bar charts:
|
||||
|
||||

|
||||
|
||||
## Pie charts
|
||||

|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public struct BarChartRow : 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)
|
||||
BarChartCell(value: self.normalizedValue(index: i), 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)
|
||||
|
||||
}
|
||||
@@ -28,6 +28,10 @@ public struct BarChartRow : View {
|
||||
.padding([.top, .leading, .trailing], 10)
|
||||
}
|
||||
}
|
||||
|
||||
func normalizedValue(index: Int) -> Double {
|
||||
return Double(self.data[index])/Double(self.maxValue)
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
@@ -13,25 +13,31 @@ public struct BarChartView : View {
|
||||
public var title: String
|
||||
public var legend: String?
|
||||
public var style: ChartStyle
|
||||
let selectionFeedbackGenerator = UISelectionFeedbackGenerator()
|
||||
public var formSize:CGSize
|
||||
public var dropShadow: Bool
|
||||
|
||||
// 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()
|
||||
// selectionFeedbackGenerator.selectionChanged()
|
||||
HapticFeedback.playSelection()
|
||||
}
|
||||
}
|
||||
}
|
||||
var isFullWidth:Bool {
|
||||
return self.style.chartFormSize == Form.large
|
||||
return self.formSize == Form.large
|
||||
}
|
||||
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.barChartStyleOne ){
|
||||
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 {
|
||||
@@ -39,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){
|
||||
@@ -51,7 +57,7 @@ public struct BarChartView : View {
|
||||
.font(.headline)
|
||||
.foregroundColor(self.style.textColor)
|
||||
}
|
||||
if(self.style.chartFormSize == Form.large && self.legend != nil && !showValue) {
|
||||
if(self.formSize == Form.large && self.legend != nil && !showValue) {
|
||||
Text(self.legend!)
|
||||
.font(.callout)
|
||||
.foregroundColor(self.style.accentColor)
|
||||
@@ -64,7 +70,7 @@ public struct BarChartView : View {
|
||||
.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 {
|
||||
if self.legend != nil && self.formSize == Form.medium {
|
||||
Text(self.legend!)
|
||||
.font(.headline)
|
||||
.foregroundColor(self.style.legendTextColor)
|
||||
@@ -72,10 +78,10 @@ public struct BarChartView : View {
|
||||
}
|
||||
|
||||
}
|
||||
}.frame(minWidth:self.style.chartFormSize.width, maxWidth: self.isFullWidth ? .infinity : self.style.chartFormSize.width, minHeight:self.style.chartFormSize.height, maxHeight:self.style.chartFormSize.height)
|
||||
}.frame(minWidth:self.formSize.width, maxWidth: self.isFullWidth ? .infinity : self.formSize.width, minHeight:self.formSize.height, maxHeight:self.formSize.height)
|
||||
.gesture(DragGesture()
|
||||
.onChanged({ value in
|
||||
self.touchLocation = value.location.x/self.style.chartFormSize.width
|
||||
self.touchLocation = value.location.x/self.formSize.width
|
||||
self.showValue = true
|
||||
self.currentValue = self.getCurrentValue()
|
||||
})
|
||||
@@ -89,8 +95,7 @@ public struct BarChartView : View {
|
||||
}
|
||||
|
||||
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)
|
||||
let index = max(0,min(self.data.count-1,Int(floor((self.touchLocation*self.formSize.width)/(self.formSize.width/CGFloat(self.data.count))))))
|
||||
return self.data[index]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ public struct Colors {
|
||||
public static let GradientLowerBlue:Color = Color(hexString: "#F1F9FF")
|
||||
public static let DarkPurple:Color = Color(hexString: "#1B205E")
|
||||
public static let BorderBlue:Color = Color(hexString: "#4EBCFF")
|
||||
|
||||
|
||||
}
|
||||
|
||||
public struct Styles {
|
||||
@@ -36,63 +34,86 @@ public struct Styles {
|
||||
backgroundColor: Color.white,
|
||||
accentColor: Colors.OrangeStart,
|
||||
secondGradientColor: Colors.OrangeEnd,
|
||||
chartFormSize: Form.medium,
|
||||
textColor: Color.black,
|
||||
legendTextColor: Color.gray)
|
||||
|
||||
public static let barChartStyleOne = ChartStyle(
|
||||
public static let barChartStyleOrangeLight = ChartStyle(
|
||||
backgroundColor: Color.white,
|
||||
accentColor: Colors.OrangeStart,
|
||||
secondGradientColor: Colors.OrangeEnd,
|
||||
chartFormSize: Form.medium,
|
||||
textColor: Color.black,
|
||||
legendTextColor: Color.gray)
|
||||
|
||||
public static let barChartStyleTwo = ChartStyle(
|
||||
public static let barChartStyleOrangeDark = ChartStyle(
|
||||
backgroundColor: Color.black,
|
||||
accentColor: Colors.OrangeStart,
|
||||
secondGradientColor: Colors.OrangeEnd,
|
||||
textColor: Color.white,
|
||||
legendTextColor: Color.gray)
|
||||
|
||||
public static let barChartStyleNeonBlueLight = ChartStyle(
|
||||
backgroundColor: Color.white,
|
||||
accentColor: Colors.GradientNeonBlue,
|
||||
secondGradientColor: Colors.GradientPurple,
|
||||
chartFormSize: Form.medium,
|
||||
textColor: Color.black,
|
||||
legendTextColor: Color.gray)
|
||||
|
||||
public static let barChartStyleThree = ChartStyle(
|
||||
public static let barChartStyleNeonBlueDark = ChartStyle(
|
||||
backgroundColor: Color.black,
|
||||
accentColor: Colors.GradientNeonBlue,
|
||||
secondGradientColor: Colors.GradientPurple,
|
||||
chartFormSize: Form.medium,
|
||||
textColor: Color.white,
|
||||
legendTextColor: Color.gray)
|
||||
|
||||
public static let barChartMidnightGreenDark = ChartStyle(
|
||||
backgroundColor: Color(hexString: "#36534D"), //3B5147, 313D34
|
||||
accentColor: Color(hexString: "#FFD603"),
|
||||
secondGradientColor: Color(hexString: "#FFCA04"),
|
||||
textColor: Color.white,
|
||||
legendTextColor: Color(hexString: "#D2E5E1"))
|
||||
|
||||
public static let barChartMidnightGreenLight = ChartStyle(
|
||||
backgroundColor: Color.white,
|
||||
accentColor: Color(hexString: "#84A094"), //84A094 , 698378
|
||||
secondGradientColor: Color(hexString: "#50675D"),
|
||||
textColor: Color.black,
|
||||
legendTextColor:Color.gray)
|
||||
|
||||
public static let pieChartStyleOne = ChartStyle(
|
||||
backgroundColor: Color.white,
|
||||
accentColor: Colors.OrangeStart,
|
||||
secondGradientColor: Colors.OrangeEnd,
|
||||
chartFormSize: Form.medium,
|
||||
textColor: Color.black,
|
||||
legendTextColor: Color.gray)
|
||||
}
|
||||
|
||||
public struct Form {
|
||||
#if os(watchOS)
|
||||
public static let small = CGSize(width:120, height:90)
|
||||
public static let medium = CGSize(width:120, height:160)
|
||||
public static let large = CGSize(width:180, height:90)
|
||||
public static let detail = CGSize(width:180, height:160)
|
||||
#else
|
||||
public static let small = CGSize(width:180, height:120)
|
||||
public static let medium = CGSize(width:180, height:240)
|
||||
public static let large = CGSize(width:360, height:120)
|
||||
public static let detail = CGSize(width:180, height:120)
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
public struct ChartStyle {
|
||||
public var backgroundColor: Color
|
||||
public var accentColor: Color
|
||||
public var secondGradientColor: Color
|
||||
public var chartFormSize: CGSize
|
||||
public var textColor: Color
|
||||
public var legendTextColor: Color
|
||||
|
||||
public init(backgroundColor: Color, accentColor: Color, secondGradientColor: Color, chartFormSize: CGSize, textColor: Color, legendTextColor: Color){
|
||||
public init(backgroundColor: Color, accentColor: Color, secondGradientColor: Color, textColor: Color, legendTextColor: Color){
|
||||
self.backgroundColor = backgroundColor
|
||||
self.accentColor = accentColor
|
||||
self.secondGradientColor = secondGradientColor
|
||||
self.chartFormSize = chartFormSize
|
||||
self.textColor = textColor
|
||||
self.legendTextColor = legendTextColor
|
||||
}
|
||||
@@ -101,7 +122,6 @@ public struct ChartStyle {
|
||||
self.backgroundColor = Color.white
|
||||
self.accentColor = Colors.OrangeStart
|
||||
self.secondGradientColor = Colors.OrangeEnd
|
||||
self.chartFormSize = formSize
|
||||
self.legendTextColor = Color.gray
|
||||
self.textColor = Color.black
|
||||
}
|
||||
@@ -123,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)
|
||||
@@ -139,3 +159,18 @@ extension Color {
|
||||
self.init(red: Double(r) / 255, green: Double(g) / 255, blue: Double(b) / 255)
|
||||
}
|
||||
}
|
||||
|
||||
class HapticFeedback {
|
||||
#if os(watchOS)
|
||||
//watchOS implementation
|
||||
static func playSelection() -> Void {
|
||||
WKInterfaceDevice.current().play(.click)
|
||||
}
|
||||
#else
|
||||
//iOS implementation
|
||||
let selectionFeedbackGenerator = UISelectionFeedbackGenerator()
|
||||
static func playSelection() -> Void {
|
||||
UISelectionFeedbackGenerator().selectionChanged()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -8,34 +8,42 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct LineChartView: View {
|
||||
let selectionFeedbackGenerator = UISelectionFeedbackGenerator()
|
||||
public struct LineChartView: View {
|
||||
// let selectionFeedbackGenerator = UISelectionFeedbackGenerator()
|
||||
@ObservedObject var data:ChartData
|
||||
public var title: String
|
||||
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 {
|
||||
didSet{
|
||||
if (oldValue != self.currentValue && showIndicatorDot) {
|
||||
selectionFeedbackGenerator.selectionChanged()
|
||||
// selectionFeedbackGenerator.selectionChanged()
|
||||
HapticFeedback.playSelection()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
let frame = CGSize(width: 180, height: 120)
|
||||
private var rateValue: Int
|
||||
|
||||
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.lineChartStyleOne ){
|
||||
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!
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
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){
|
||||
@@ -44,8 +52,12 @@ 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)
|
||||
@@ -70,7 +82,7 @@ struct LineChartView: View {
|
||||
.frame(width: frame.width, height: frame.height)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 20))
|
||||
.offset(x: 0, y: 0)
|
||||
}.frame(width: self.style.chartFormSize.width, height: self.style.chartFormSize.height)
|
||||
}.frame(width: self.formSize.width, height: self.formSize.height)
|
||||
}
|
||||
.gesture(DragGesture()
|
||||
.onChanged({ value in
|
||||
|
||||
@@ -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
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,16 @@ public struct PieChartView : View {
|
||||
public var title: String
|
||||
public var legend: String?
|
||||
public var style: ChartStyle
|
||||
public init(data: [Int], title: String, legend: String? = nil, style: ChartStyle = Styles.pieChartStyleOne ){
|
||||
public var formSize:CGSize
|
||||
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 {
|
||||
@@ -25,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)
|
||||
@@ -46,7 +51,7 @@ public struct PieChartView : View {
|
||||
}
|
||||
|
||||
}
|
||||
}.frame(width: self.style.chartFormSize.width, height: self.style.chartFormSize.height)
|
||||
}.frame(width: self.formSize.width, height: self.formSize.height)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
Reference in New Issue
Block a user