Creating multiple circular view with text as labeling in front of it in swiftui

Viewed 61

How to create this view in SwiftUI? I want the labeling in front of it.

picture 1

I have done up to this mark, I don't know how to add the label in front of it.

picture 2

This is the Ring View I Created

struct RingView : View {
    
    @State var max : Double
    let lineWidth : CGFloat
    let foreGroundColor : Color
    let percentage : Double
    
    var body : some View {
        GeometryReader{ geometery in
            ZStack{
                //Track
                RingShape()
                    .stroke(style: StrokeStyle(lineWidth: lineWidth ))
                    .fill(Color.white)
                //Animated ring
                RingShape(percent: percentage)
                    .stroke(style: StrokeStyle(lineWidth: lineWidth , lineCap: .round))
                    .fill(foreGroundColor)
                
            }
            .animation(Animation.easeIn(duration: 1))
            .padding(lineWidth/2)
            
        }
        
    }
}

This is the shape of the Ring

struct RingShape : Shape {
    
    var max : Double
    var percent : Double
    let startAngle : Double
    
    typealias AnimatableData = Double
    var animatableData: Double {
        get {
            return percent
        }
        set {
            percent = newValue
        }
    }
    init(
        percent : Double = 100 ,
        startAngle : Double = -90,
        max : Double = 0.0
        
    ){
        
        self.percent = percent
        self.startAngle = startAngle
        self.max = max
    }
    
    
    static func percentAngle(startAngle : Double , percent : Double , max : Double) -> Double {
        if percent > 100 {
            return (100 / 100 * 180) + startAngle
        }else if(percent == 0){
            return (1)+startAngle
        }else {
        return (percent / 100 * 180) + startAngle
        }
    }
    
    func path(in rect: CGRect) -> Path {
        
        let width = rect.width
        let height = rect.height
        let radius = min(width, height)
        let center = CGPoint(x: width/2, y: height/2)
        let endAngle = Self.percentAngle(startAngle: startAngle, percent: percent , max: max)
        
        
        return Path { path in
            path.addArc(
                center: center,
                radius: radius,
                startAngle: Angle(degrees: startAngle),
                endAngle: Angle(degrees: endAngle),
                clockwise: false
            )
        }
    }
    
}

Above is the code for image 2 but I need to improve and show my view as image 1

I am calling RingView in this view .

struct CircularView: View {
    
    @EnvironmentObject var model : fetchedData
    @State var max : Double
    
    
    var body: some View {
        VStack {
            ZStack{
                
                Ring(
                    max: max, lineWidth: 10,
                    foreGroundColor: getColor(lowLimit: 50, highLimit: 100, value: model.singleData.result.CO2),
                    percentage: (model.singleData.result.CO2 )
                )
                .frame(width: 70, height: 70)
                Ring(
                    max: max,
                    lineWidth: 10,
                    foreGroundColor: getColor(lowLimit: 50, highLimit: 500, value: model.singleData.result.PM25),
                    percentage: (model.singleData.result.PM25 )
                )
                .frame(width: 90, height: 90)
                Ring(
                    max: max,
                    lineWidth: 10,
                    foreGroundColor: getColor(lowLimit: 5, highLimit: 10, value: model.singleData.result.CO),
                    percentage: (model.singleData.result.CO )
                )
                .frame(width: 110, height: 110)
                Ring(
                    max: max,
                    lineWidth: 10,
                    foreGroundColor: getColor(lowLimit: 50, highLimit: 500, value: model.singleData.result.VOC),
                    percentage: (model.singleData.result.VOC )
                )
                .frame(width: 130, height: 130)
                Ring(
                    max: max,
                    lineWidth: 10,
                    foreGroundColor: getColor(lowLimit: 700, highLimit: 1000, value: model.singleData.result.CO2),
                    percentage: (model.singleData.result.CO2)
                )
                .frame(width: 150, height: 150)
            }
            .frame(width: 300, height: 300)
        }
    }
}
0 Answers
Related