AutorÃa | Ultima modificación | Ver Log |
//// PieChartView.swift// twogetskills//// Created by Efrain Yanez Recanatini on 3/10/22.//import SwiftUI@available(OSX 10.15, *)public struct PieChartView: View {public let values: [Double]public var total: Doublepublic let names: [String]public let formatter: (Double) -> Stringpublic var colors: [Color]public var backgroundColor: Colorpublic var widthFraction: CGFloatpublic var innerRadiusFraction: CGFloatpublic var chartSize : CGFloat@State private var activeIndex: Int = -1var slices: [PieSliceData] {let sum = values.reduce(0, +)var endDeg: Double = 0var tempSlices: [PieSliceData] = []for (i, value) in values.enumerated() {let degrees: Double = value * 360 / sumtempSlices.append(PieSliceData(startAngle: Angle(degrees: endDeg), endAngle: Angle(degrees: endDeg + degrees), text: "", color: self.colors[i]))endDeg += degrees}//text: String(format: "%.0f%%", value * 100 / sum)return tempSlices}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){self.values = valuesself.names = namesself.formatter = formatterself.colors = colorsself.backgroundColor = backgroundColorself.widthFraction = widthFractionself.innerRadiusFraction = innerRadiusFractionself.chartSize = chartSizeself.total = total}public var body: some View {GeometryReader { geometry inVStack{ZStack{ForEach(0..<self.values.count){ i inPieSlice(pieSliceData: self.slices[i]).scaleEffect(self.activeIndex == i ? 1.03 : 1).animation(Animation.spring())}/*.frame(width: widthFraction * geometry.size.width, height: widthFraction * geometry.size.width)*/.frame(width: widthFraction * self.chartSize, height: widthFraction * self.chartSize).gesture(DragGesture(minimumDistance: 0).onChanged { value in/*let radius = 0.5 * widthFraction * geometry.size.width*/let radius = 0.5 * self.chartSize * geometry.size.widthlet diff = CGPoint(x: value.location.x - radius, y: radius - value.location.y)let dist = pow(pow(diff.x, 2.0) + pow(diff.y, 2.0), 0.5)if (dist > radius || dist < radius * innerRadiusFraction) {self.activeIndex = -1return}var radians = Double(atan2(diff.x, diff.y))if (radians < 0) {radians = 2 * Double.pi + radians}for (i, slice) in slices.enumerated() {if (radians < slice.endAngle.radians) {self.activeIndex = ibreak}}}.onEnded { value inself.activeIndex = -1})/*Circle().fill(self.backgroundColor).frame(width: widthFraction * geometry.size.width * innerRadiusFraction, height: widthFraction * geometry.size.width * innerRadiusFraction)*/Circle().fill(Color.white).frame(width: widthFraction * self.chartSize * innerRadiusFraction, height: widthFraction * self.chartSize * innerRadiusFraction)VStack {/*Text(self.activeIndex == -1 ? "Total" : names[self.activeIndex]).font(.title).foregroundColor(Color.gray)Text(self.formatter(self.activeIndex == -1 ? values.reduce(0, +) : values[self.activeIndex])).font(.title)*/Text( self.formatter(total)).font(.title)}}//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, +)) })}.background(self.backgroundColor).foregroundColor(Color.gray)}}}@available(OSX 10.15, *)struct PieChartRows: View {var colors: [Color]var names: [String]var values: [String]var percents: [String]var body: some View {VStack{ForEach(0..<self.values.count){ i inHStack {RoundedRectangle(cornerRadius: 5.0).fill(self.colors[i]).frame(width: 20, height: 20)Text(self.names[i])Spacer()VStack(alignment: .trailing) {Text(self.values[i])Text(self.percents[i]).foregroundColor(Color.gray)}}}}}}@available(OSX 10.15.0, *)struct PieChartView_Previews: PreviewProvider {static var previews: some View {PieChartView(values: [20,80], names: ["Rent", "Transport", "Education"], formatter: {value in String(format: "%.0f%%", value)})}}//"$%.2f"