willdale / SwiftUICharts

A charts / plotting library for SwiftUI. Works on macOS, iOS, watchOS, and tvOS and has accessibility features built in.
MIT License
843 stars 105 forks source link

BarChart Didn't Show Correctly When Replacing Point in BarDataSet #191

Closed owenzhao closed 2 years ago

owenzhao commented 2 years ago
    if let barChartData = barChartData {
        BarChart(chartData: barChartData)
            .touchOverlay(chartData: barChartData)
            .xAxisLabels(chartData: barChartData)
            .yAxisLabels(chartData: barChartData)
            .floatingInfoBox(chartData: barChartData)
    }

    private func appendBarChartData(_ log:DTLog, limit: Int) {
        let xAxisLabel = DateFormatter.localizedString(from: log.startTime, dateStyle: .none, timeStyle: .medium)
        let color = ColourStyle(colour: log.connected ? .green : .red)
        let point = BarChartDataPoint(value: Double(log.delay), xAxisLabel: xAxisLabel, colour: color)
        let style = BarStyle(barWidth: 1, cornerRadius: CornerRadius(topLeft: 5, topRight: 5, bottomLeft: 5, bottomRight: 5),
                             colourFrom: .barStyle, colour: color)

        if barChartData == nil {
            let points = (1...limit).map { _ in getEmptyBarChartDataPoint() }
            barChartData = BarChartData(dataSets: BarDataSet(dataPoints: points),
                                        barStyle: style)
        }

        if let barChartData = barChartData {
            if let zeroIndex = barChartData.dataSets.dataPoints.firstIndex(where: { $0.value == 0 }) {
                barChartData.dataSets.dataPoints[zeroIndex] = point
            } else {
                barChartData.dataSets.dataPoints.removeFirst()
                barChartData.dataSets.dataPoints.append(point)
            }
        }
    }

    private func getEmptyBarChartDataPoint() -> BarChartDataPoint {
        return BarChartDataPoint(value: 0, colour: .init(colour: .yellow))
    }

When the app ran, the bar chart didn't show properly. The overlay and info box were correct. But the bar didn't draw.

https://user-images.githubusercontent.com/2182896/165194101-6a525950-dfe9-40ef-9dc6-cc7417bd7e0e.mov

owenzhao commented 2 years ago

A Workaround I found was to recreate BarChartData each time.

private func appendBarChartData(_ log:DTLog, limit: Int) {
        let xAxisLabel = DateFormatter.localizedString(from: log.startTime, dateStyle: .none, timeStyle: .medium)
        let color = ColourStyle(colour: log.connected ? .green : .red)
        let point = BarChartDataPoint(value: Double(log.delay), xAxisLabel: xAxisLabel, colour: color)
        let style = BarStyle(barWidth: 1, cornerRadius: CornerRadius(topLeft: 5, topRight: 5, bottomLeft: 5, bottomRight: 5),
                             colourFrom: .barStyle, colour: color)

        if barChartData == nil {
            let points = (1...limit).map { _ in getEmptyBarChartDataPoint() }
            barChartData = BarChartData(dataSets: BarDataSet(dataPoints: points),
                                        barStyle: style)
        }

        if let barChartData = barChartData {
            var points = barChartData.dataSets.dataPoints
            points.removeFirst()
            points.append(point)
            self.barChartData = BarChartData(dataSets: BarDataSet(dataPoints: points),
                                        barStyle: style)
        }
    }
willdale commented 2 years ago

v2.10.0 should fix this.

owenzhao commented 2 years ago

I forked this project and I thought for a period updated bar chart, my new animation was fitter.

https://github.com/owenzhao/SwiftUICharts