// // StepViewController.swift // Twear // // Created by yangbin on 2021/11/19. // import UIKit import Charts import SwiftDate class StepViewController: UIViewController, DateSegmentViewDelegate, RangeSliderDelegate, ChartViewDelegate, BluetoothSyncDelegate { @IBOutlet weak var dateSegmentView: DateSegmentView! @IBOutlet weak var lineChartView: LineChartView! @IBOutlet weak var sliderView: RangeSliderView! @IBOutlet weak var dateLabel: UILabel! @IBOutlet weak var stepLabel: UILabel! @IBOutlet weak var calorieLabel: UILabel! @IBOutlet weak var dayStepLabel: UILabel! // @IBOutlet weak var analysisLabel: UILabel! @IBOutlet weak var goButton: UIButton! @IBOutlet weak var stepsGoalLabel: UILabel! @IBOutlet weak var stepSliderLabel: UILabel! @IBOutlet weak var goalPerLabel: UILabel! @IBOutlet weak var stepProgressView: StepProgressView! @IBOutlet weak var circleProgress1: CircleProgressView! @IBOutlet weak var circleProgress2: CircleProgressView! @IBOutlet weak var circleProgress3: CircleProgressView! @IBOutlet weak var circleProgress4: CircleProgressView! @IBOutlet weak var circleProgress5: CircleProgressView! @IBOutlet weak var circleProgress6: CircleProgressView! @IBOutlet weak var circleProgress7: CircleProgressView! private var dateType: DateType = .day let user = UserInfo var subStepArray: [Int] = [] private var selectedXValue: Double = 0 private var selectedDate = Date() lazy private var monthDays = DateInRegion().monthDays private var points: [Double] = [] // private var maxStep = 11000 private var stepArray: [StepModel] = [] { didSet { if stepArray.count == 0 { resetLabel() } else { stepLabel.text = "\(stepArray.first?.number ?? 0)" } points = [] let step = stepArray.max{$0.number < $1.number} let maxStep = step?.number ?? user.stepsGoal if dateType != .day && maxStep != 0 { if maxStep < 500 { lineChartView.leftAxis.axisMaximum = 500 * 1.2 lineChartView.leftAxis.granularity = 100 } else { lineChartView.leftAxis.axisMaximum = Double(maxStep) * 1.2 lineChartView.leftAxis.granularity = 500 } } else { // lineChartView.leftAxis.axisMaximum = Double(user.stepsGoal) } } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationController?.setNavigationBarHidden(true, animated: true) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) BluetoothManager.shared.unRegisterSyncDelegate(self) } override func viewDidLoad() { super.viewDidLoad() goButton.setTitle(" \(LocString("去步行")) ", for: .normal) dateSegmentView.selectedColor = UIColor.rgbColorFromHex(0x3EE1CD) dateSegmentView.delegate = self sliderView.delegate = self BluetoothManager.shared.registerSyncDelegate(self) updateWeekProgress() view.layoutIfNeeded() setupChartView() didSelectedDate(date: DateInRegion(), dateType: .day) NotificationCenter.default.addObserver(self, selector: #selector(refreshSteps), name: Notification.Name("UpdateStepData"), object: nil) } @objc func refreshSteps() { print("更新步数") didSelectedDate(date: DateInRegion(selectedDate, region: .current), dateType: dateType) } private func updateWeekProgress() { let progressArray: [CircleProgressView] = [circleProgress1, circleProgress2, circleProgress3, circleProgress4, circleProgress5, circleProgress6, circleProgress7] let array = StepModel.getLastWeekSteps() for (i, step) in array.enumerated() { progressArray[i].label.text = step.date!.toString(.custom("MM/dd")) progressArray[i].value = step.percent } } func didReceiveStep() { didSelectedDate(date: DateInRegion(selectedDate), dateType: dateType) } //MARK: DateSegmentViewDelegate func didSelectedDate(date: DateInRegion, dateType: DateType) { self.dateType = dateType monthDays = date.monthDays selectedDate = date.date switch dateType { case .day: stepArray = StepModel.getStepsByDay(selectedDate) print("已更新") dateLabel.text = date.dateAt(.startOfDay).toString(.custom("HH:mm")) case .week: stepArray = StepModel.getStepsByWeek(selectedDate) dateLabel.text = (date.dateAt(.startOfWeek)+1.days).toString(.custom("yyyy.MM.dd")) + " 周一" case .month: stepArray = StepModel.getStepsByMonth(selectedDate) dateLabel.text = date.dateAt(.startOfMonth).toString(.custom("yyyy.MM.dd")) case .year: stepArray = StepModel.getStepsByYear(selectedDate) dateLabel.text = date.dateAtStartOf(.year).toString(.custom("yyyy.MM")) } updateChartView() setupSliderViewScale() } //MARK: RangeSliderDelegate func sliderDidChanged(index: Int) { lineChartView.highlightValues([Highlight(x: points[index], y: 0, dataSetIndex: 0)]) updateLable(index) } //MARK: ChartViewDelegate func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) { if stepArray.count == 1 { lineChartView.highlightValues([Highlight(x: points[0], y: 0, dataSetIndex: 0)]) } else { sliderView.didSelectedValue(entry.x) } } @IBAction func share(_ sender: Any) { let shareView = ShareView(view.captureImage) shareView.show() } private func resetLabel() { stepLabel.text = "--" dayStepLabel.text = "--" calorieLabel.text = "--" updateProgressView(StepModel()) // analysisLabel.text = "\(LocString("亲,您已超过"))0%\(LocString("的同类用户"))" } private func updateProgressView(_ step: StepModel) { stepsGoalLabel.text = "\(user.stepsGoal)" stepSliderLabel.text = "\(step.number)" // let per = step.percent goalPerLabel.text = "\(step.percent)%" stepProgressView.value = step.percent } private func updateLable(_ index: Int) { if stepArray.count == 0 {//|| stepArray[index].number == 0 { resetLabel() return } if dateType == .day { if subStepArray.count-1 >= index { stepLabel.text = "\(subStepArray[index])" } if let subStep = stepArray.last { calorieLabel.text = "\(String(format:"%02d", Int(subStep.calorie)))" } } else { stepLabel.text = "\(stepArray[index].number)"//"\(stepArray.sum(\.number))"// calorieLabel.text = "\(String(format:"%02d", Int(stepArray.sum(\.calorie))))" } // stepsDistanceLabel.toUnitMode1(title: LocString("热量"), text: String(format:"%02d",Int(step.calorie)), unit: LocString("千卡"), font: RegularFont(13), unitFont: LightFont(11)) if dateType == .day { if stepArray.count > 0, let step = stepArray.last { dayStepLabel.text = "\(step.number)" updateProgressView(step) } } else { dayStepLabel.text = "\(stepArray.sum(\.number))"//"\(stepArray[index].number)" } let sDate = stepArray[index].date! var number = stepArray[index].number switch dateType { case .day: dateLabel.text = sDate.toString(.custom("HH:mm")) number = stepArray.last?.number ?? 0 case .week: dateLabel.text = sDate.toString(.custom("yyyy.MM.dd")) + " " + sDate.weekText case .month: dateLabel.text = sDate.toString(.custom("yyyy.MM.dd")) case .year: dateLabel.text = sDate.toString(.custom("yyyy.MM")) } var per: String = "0" switch number { case 0..<100: per = "0" case 100..<8000: per = String(format:"%.1f",Float(number)/100) case 8000..<10000: per = String(format:"%.1f",80+Float(number)/200) case 10000..<20000: per = String(format:"%.1f",90+Float(number)/1000) default: per = "99.9" } // analysisLabel.text = "\(LocString("亲,您已超过"))\(per)%\(LocString("的同类用户"))" } private func updateChartView() { let xAxis = lineChartView.xAxis 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 } var dataEntries = [ChartDataEntry]() var array: [Int] = [] for (i, step) in stepArray.enumerated() { // if step.number > 0 { var number: Int = step.number var pointX: Double = 0 switch dateType { case .day: if step.date!.hour == 23 { pointX = 24 } else { pointX = Double((step.date!).hour)+Double(step.date!.minute)/60.0 } if i > 0 { number = step.number - stepArray[i-1].number if number < 0 { number = 0 } } array.append(number) subStepArray = array if let max = subStepArray.max() { if max == 0 { lineChartView.leftAxis.axisMaximum = Double(user.stepsGoal) lineChartView.leftAxis.granularity = 500 } else if max < 1000 { lineChartView.leftAxis.granularity = 100 lineChartView.leftAxis.axisMaximum = 1000 * 1.2 } else { lineChartView.leftAxis.granularity = 500 lineChartView.leftAxis.axisMaximum = Double(max) * 1.2 } } else { lineChartView.leftAxis.granularity = 500 lineChartView.leftAxis.axisMaximum = Double(user.stepsGoal) } case .week: pointX = Double(step.date!.weekIndex) case .month: pointX = Double(step.date!.day-1) case .year: pointX = Double(step.date!.month-1) } points.append(pointX) dataEntries.append(ChartDataEntry(x: pointX, y: Double(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 = true//选中拐点,是否开启高亮效果(显示十字线) dataSet.highlightLineWidth = 1 dataSet.highlightColor = UIColor.rgbColorFromHex(0x1DDCC5)// 十字线颜色 dataSet.drawHorizontalHighlightIndicatorEnabled = false dataSet.mode = .horizontalBezier dataSet.setColor(UIColor.rgbColorFromHex(0x1DDCC5)) // if dataEntries.count == 1 { // dataSet.lineWidth = 5 // } else { 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)]) } func setupSliderViewScale() { var endPointX: Int = 0 switch dateType { case .day: endPointX = 24 case .week: endPointX = 6 case .month: endPointX = monthDays-1 case .year: endPointX = 11 } sliderView.setDrawSpace(startPointX: getChartViewX(0), endPointX: getChartViewX(endPointX), range: 0...endPointX, points: points, imageName: "slider_step", isLast: true) } private func getChartViewX(_ x: Int) -> CGFloat { return lineChartView.pixelForValues(x: Double(x), y: 0, axis: .left).x } func setupChartView() { lineChartView.delegate = self 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 = 11000 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 } @IBAction func gotoReferenceVC(_ sender: Any) { let vc = UIStoryboard.loadViewControllerIdentifier(storyboardName: "Home", identifier: "StepReferenceVC") navigationController?.pushViewController(vc, animated: true) } @IBAction func gotoMotionVC(_ sender: Any) { navigationController?.tabBarController?.selectedIndex = 1 self.navigationController?.popToRootViewController(animated: false) } @IBAction func back(_ sender: Any) { navigationController?.popViewController(animated: true) } deinit { print("deinit\(NSStringFromClass(type(of: self)))!!!!!!!") } }