StepReportCell.swift 7.54 KB
//
//  StepReportCell.swift
//  Twear
//
//  Created by yangbin on 2022/1/1.
//

import UIKit
import Charts
import SwiftDate

class StepReportCell: UICollectionViewCell {
    
    @IBOutlet weak var lineChartView: LineChartView!
    @IBOutlet weak var stepLabel: UILabel!
    @IBOutlet weak var stepsGoalLabel: UILabel!
    @IBOutlet weak var dateLabel: UILabel!
    
    @IBOutlet weak var detailLabel: UILabel!
    var dateType: DateType = .day {
        didSet {
            updateChartView()
        }
    }
    
    private let goal: Int = UserInfo.stepsGoal
    lazy private var monthDays = DateInRegion().monthDays
    var stepArray: [StepModel] = []
    
    
    
    private func updateChartView() {
        setupChartView()
        let nowDate = DateInRegion().date
        switch dateType {
        case .day:
            stepArray = StepModel.getStepsByDay(nowDate)
            dateLabel.text = nowDate.dateAt(.startOfDay).toString(.custom("yyyy.MM.dd"))
        case .week:
            stepArray = StepModel.getStepsByWeek(nowDate)
            dateLabel.text = ((nowDate-1.days).dateAt(.startOfWeek)+1.days).toString(.custom("MM.dd")) + "-" + ((nowDate-1.days).dateAt(.endOfWeek)+1.days).toString(.custom("MM.dd"))
        case .month:
            stepArray = StepModel.getStepsByMonth(nowDate)
            dateLabel.text = nowDate.toString(.custom("yyyy.MM"))
        case .year:
            stepArray = StepModel.getStepsByYear(nowDate)
            dateLabel.text = "\(nowDate.year).01-\(nowDate.year).12"
        }
        var maxStep = stepArray.max(\.number)?.number ?? goal
        if maxStep <= goal {
            maxStep = goal
        }
        
        if dateType == .day {
            detailLabel.text = LocString("目标步数")
        } else {
            detailLabel.text = LocString("日均步数")
        }
        
        if stepArray.count == 0 {
            setSteps(nil)
        } else {
            if dateType == .day {
                if let step = stepArray.last {
                    setSteps(step.number)
                }
                
                setStepsGoal(goal)
            } else {
                lineChartView.leftAxis.axisMaximum = maxStep == goal ? Double(goal) : Double(maxStep) * 1.2
                setSteps(stepArray.sum(\.number))
                setStepsGoal(stepArray.average(\.number))
            }
        }
        
        var dataEntries = [ChartDataEntry]()
        
        for step in stepArray {
            var pointX: Double = 0
            switch dateType {
            case .day:
                if step.date!.hour == 23 {
                    pointX = 24
                } else {
                    pointX = Double((step.date!+1.hours).hour)+Double(step.date!.minute)/60.0
                }
            case .week:
                pointX = Double(step.date!.weekIndex)
            case .month:
                pointX = Double(step.date!.day-1)
            case .year:
                pointX = Double(step.date!.month-1)
            }
            dataEntries.append(ChartDataEntry(x: pointX, y: Double(step.number)))
        }
        
        if stepArray.count == 1 {
            dataEntries.append(ChartDataEntry(x: dataEntries[0].x+0.2, y: dataEntries[0].y))
        }

        let dataSet = LineChartDataSet(entries: dataEntries)
        dataSet.drawCirclesEnabled = false
        dataSet.drawValuesEnabled = false
        dataSet.highlightEnabled = false//选中拐点,是否开启高亮效果(显示十字线)
        dataSet.highlightLineWidth = 1
        dataSet.highlightColor = UIColor.rgbColorFromHex(0x1DDCC5)// 十字线颜色
        dataSet.drawHorizontalHighlightIndicatorEnabled = false
        dataSet.mode = .horizontalBezier
        dataSet.setColor(UIColor.rgbColorFromHex(0x1DDCC5))
        dataSet.lineWidth = 1
        
        dataSet.drawFilledEnabled = true //填充绘制
        let gradientColors = [UIColor.rgbColorFromHex(0x1DDCC5).cgColor, UIColor.rgbColorFromHex(0xFFFFFF).cgColor]
        let gradient = CGGradient(colorsSpace: nil, colors: gradientColors as CFArray, locations: [1.0, 0.0])
        dataSet.fillAlpha = 1
        dataSet.fill = Fill(linearGradient: gradient!, angle: 90)
        lineChartView.data = LineChartData(dataSets: [dataSet])
//        lineChartView.highlightValues([Highlight(x: 0, y: 0, dataSetIndex: 0)])
    }
    
    private func setSteps(_ steps: Int?) {
        if steps == nil {
            stepLabel.toUnitMode(text: "--", unit: " \(LocString("步"))", font: BoldFont(23), unitFont: RegularFont(13))
        } else {
            stepLabel.toUnitMode(text: "\(steps!)", unit: " \(LocString("步"))", font: BoldFont(23), unitFont: RegularFont(13))
        }
        
    }
    
    private func setStepsGoal(_ steps: Int) {
        stepsGoalLabel.toUnitMode(text: "\(steps)", unit: " \(LocString("步"))", font: BoldFont(23), unitFont: RegularFont(13))
    }
    
    func setupChartView() {
        lineChartView.chartDescription?.enabled = false //图描述
        lineChartView.legend.enabled = false //左下角图例
        lineChartView.setScaleEnabled(false) //可滑动
        lineChartView.rightAxis.enabled = false //不绘制右边轴的信息
        
        let leftAxis = lineChartView.leftAxis
        leftAxis.labelTextColor = ChartsTextColor
        leftAxis.labelFont = ChartsTextFont(11)
        leftAxis.yOffset = -4
        leftAxis.xOffset = -3
        leftAxis.gridLineDashLengths = [2.0, 2.0]  //设置虚线样式的网格线
        leftAxis.gridColor = LineColor
        leftAxis.gridLineWidth = 1
        leftAxis.axisLineWidth = 0
        leftAxis.drawGridLinesBehindDataEnabled = false
        leftAxis.labelPosition = .insideChart
        
        leftAxis.axisMinimum = 0 //设置左侧Y轴最小值
        leftAxis.axisMaximum = Double(goal)
        leftAxis.granularity = 500
        
        let litmitLine = ChartLimitLine(limit: 0, label: "")
        litmitLine.lineWidth = 1
        litmitLine.lineColor = LineColor
        leftAxis.addLimitLine(litmitLine)
        leftAxis.drawLimitLinesBehindDataEnabled = false  //设置限制线绘制在折线图的后面
        
        
        let xAxis = lineChartView.xAxis
        xAxis.granularity = 1 //间隔
        xAxis.labelPosition = .bottom
        xAxis.labelFont = ChartsTextFont(11)
        xAxis.labelTextColor = ChartsTextColor
        xAxis.drawGridLinesBehindDataEnabled = false
        xAxis.axisLineColor = LineColor
        xAxis.axisLineWidth = 1
        xAxis.gridLineDashLengths = [6, 666]
        xAxis.gridColor = LineColor
        xAxis.drawAxisLineEnabled = false
        
        switch dateType {
        case .day:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: DayXValues)
            xAxis.labelCount = 9

            xAxis.axisMinimum = -2.9
            xAxis.axisMaximum = 24 + 2
        case .week:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: WeekXValues)
            xAxis.labelCount = 7
            xAxis.axisMinimum = -0.8
            xAxis.axisMaximum = 6 + 0.8
        case .month:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: MonthXValues(monthDays))
            xAxis.labelCount = 8
            xAxis.axisMinimum = -3.5
            xAxis.axisMinLabels = 8
            xAxis.axisMaximum = Double(monthDays-1) + 2.1
        case .year:
            xAxis.valueFormatter = IndexAxisValueFormatter(values: MonthValues)
            xAxis.labelCount = 12
            xAxis.axisMinimum = -1.3
            xAxis.axisMaximum = 11 + 0.8
        }
        


    }
    
    
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

}