Proyectos de Subversion Iphone Microlearning - Inconcert

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
//
2
//  PieChartView.swift
3
//  twogetskills
4
//
5
//  Created by Efrain Yanez Recanatini on 3/10/22.
6
//
7
 
8
import SwiftUI
9
 
10
@available(OSX 10.15, *)
11
public struct PieChartView: View {
12
    public let values: [Double]
13
    public var total: Double
14
    public let names: [String]
15
    public let formatter: (Double) -> String
16
 
17
    public var colors: [Color]
18
    public var backgroundColor: Color
19
 
20
    public var widthFraction: CGFloat
21
    public var innerRadiusFraction: CGFloat
22
    public var chartSize : CGFloat
23
 
24
 
25
 
26
    @State private var activeIndex: Int = -1
27
 
28
    var slices: [PieSliceData] {
29
        let sum = values.reduce(0, +)
30
        var endDeg: Double = 0
31
        var tempSlices: [PieSliceData] = []
32
 
33
        for (i, value) in values.enumerated() {
34
            let degrees: Double = value * 360 / sum
35
            tempSlices.append(PieSliceData(startAngle: Angle(degrees: endDeg), endAngle: Angle(degrees: endDeg + degrees), text: "", color: self.colors[i]))
36
            endDeg += degrees
37
        }
38
 
39
        //text: String(format: "%.0f%%", value * 100 / sum)
40
        return tempSlices
41
    }
42
 
43
    public init(values:[Double], names: [String] = [], formatter: @escaping (Double) -> String, colors: [Color] = [Color.blue, Color.green, Color.orange], backgroundColor: Color = Color(red: 21 / 255, green: 24 / 255, blue: 30 / 255, opacity: 1.0), widthFraction: CGFloat = 0.75, innerRadiusFraction: CGFloat = 0.60, chartSize : CGFloat = 250, total : Double = 0){
44
        self.values = values
45
        self.names = names
46
        self.formatter = formatter
47
 
48
        self.colors = colors
49
        self.backgroundColor = backgroundColor
50
        self.widthFraction = widthFraction
51
        self.innerRadiusFraction = innerRadiusFraction
52
 
53
        self.chartSize = chartSize
54
        self.total = total
55
    }
56
 
57
    public var body: some View {
58
        GeometryReader { geometry in
59
 
60
            VStack{
61
                ZStack{
62
                    ForEach(0..<self.values.count){ i in
63
                        PieSlice(pieSliceData: self.slices[i])
64
                            .scaleEffect(self.activeIndex == i ? 1.03 : 1)
65
                            .animation(Animation.spring())
66
                    }
67
                    /*.frame(width: widthFraction * geometry.size.width, height: widthFraction * geometry.size.width)*/
68
                    .frame(width: widthFraction * self.chartSize, height: widthFraction * self.chartSize)
69
                    .gesture(
70
                        DragGesture(minimumDistance: 0)
71
                            .onChanged { value in
72
                                /*
73
                                let radius = 0.5 * widthFraction * geometry.size.width
74
                                    */
75
                                let radius = 0.5 * self.chartSize * geometry.size.width
76
                                let diff = CGPoint(x: value.location.x - radius, y: radius - value.location.y)
77
                                let dist = pow(pow(diff.x, 2.0) + pow(diff.y, 2.0), 0.5)
78
                                if (dist > radius || dist < radius * innerRadiusFraction) {
79
                                    self.activeIndex = -1
80
                                    return
81
                                }
82
                                var radians = Double(atan2(diff.x, diff.y))
83
                                if (radians < 0) {
84
                                    radians = 2 * Double.pi + radians
85
                                }
86
 
87
                                for (i, slice) in slices.enumerated() {
88
                                    if (radians < slice.endAngle.radians) {
89
                                        self.activeIndex = i
90
                                        break
91
                                    }
92
                                }
93
                            }
94
                            .onEnded { value in
95
                                self.activeIndex = -1
96
                            }
97
                    )
98
                    /*
99
                    Circle()
100
                        .fill(self.backgroundColor)
101
                        .frame(width: widthFraction * geometry.size.width * innerRadiusFraction, height: widthFraction * geometry.size.width * innerRadiusFraction)*/
102
 
103
                    Circle()
104
                        .fill(Color.white)
105
                        .frame(width: widthFraction * self.chartSize * innerRadiusFraction, height: widthFraction * self.chartSize * innerRadiusFraction)
106
 
107
                    VStack {
108
                        /*
109
                        Text(self.activeIndex == -1 ? "Total" : names[self.activeIndex])
110
                            .font(.title)
111
                            .foregroundColor(Color.gray)
112
 
113
                         Text(self.formatter(self.activeIndex == -1 ? values.reduce(0, +) : values[self.activeIndex]))
114
                             .font(.title)
115
 */
116
 
117
                        Text( self.formatter(total))
118
                            .font(.title)
119
                    }
120
 
121
                }
122
                //PieChartRows(colors: self.colors, names: self.names, values: self.values.map { self.formatter($0) }, percents: self.values.map { String(format: "%.0f%%", $0 * 100 / self.values.reduce(0, +)) })
123
            }
124
            .background(self.backgroundColor)
125
            .foregroundColor(Color.gray)
126
        }
127
 
128
    }
129
}
130
 
131
@available(OSX 10.15, *)
132
struct PieChartRows: View {
133
    var colors: [Color]
134
    var names: [String]
135
    var values: [String]
136
    var percents: [String]
137
 
138
 
139
    var body: some View {
140
        VStack{
141
            ForEach(0..<self.values.count){ i in
142
                HStack {
143
                    RoundedRectangle(cornerRadius: 5.0)
144
                        .fill(self.colors[i])
145
                        .frame(width: 20, height: 20)
146
                    Text(self.names[i])
147
                    Spacer()
148
                    VStack(alignment: .trailing) {
149
                        Text(self.values[i])
150
                        Text(self.percents[i])
151
                            .foregroundColor(Color.gray)
152
                    }
153
                }
154
            }
155
        }
156
    }
157
}
158
 
159
@available(OSX 10.15.0, *)
160
struct PieChartView_Previews: PreviewProvider {
161
    static var previews: some View {
162
        PieChartView(values: [20,80], names: ["Rent", "Transport", "Education"], formatter: {value in String(format: "%.0f%%", value)})
163
    }
164
}
165
 
166
//"$%.2f"