imaNNeo / fl_chart

FL Chart is a highly customizable Flutter chart library that supports Line Chart, Bar Chart, Pie Chart, Scatter Chart, and Radar Chart.
https://flchart.dev
MIT License
6.77k stars 1.74k forks source link

TouchedSpotIndicator duplicates when updating chart #1627

Open danieljosua1 opened 5 months ago

danieljosua1 commented 5 months ago

https://github.com/imaNNeo/fl_chart/assets/75301212/72fc4053-b223-4c97-b779-6821ceadf15e

I'm encountering an issue where the TouchedSpotIndicator duplicates when scrolling over the Line Chart. I've implemented an update mechanism that keeps the blue line aligned with the finger's position. Is there a solution available for this bug? I've attached a brief example for reproduction purposes. Thanks in advance!


import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        useMaterial3: true,
      ),
      home: const LineChartSample2(),
    );
  }
}

class LineChartSample2 extends StatefulWidget {
  const LineChartSample2({super.key});

  @override
  State<LineChartSample2> createState() => _LineChartSample2State();
}

class _LineChartSample2State extends State<LineChartSample2> {
  final originList = List.generate(300, (index) => FlSpot(index.toDouble(), Random().nextInt(1000).toDouble()));
  late List<FlSpot> testList = originList;

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Align(
        child: AspectRatio(
          aspectRatio: 1.70,
          child: LineChart(
            LineChartData(
              lineTouchData: LineTouchData(
                getTouchLineStart: (pointData, index) => -double.infinity,
                getTouchLineEnd: (_, __) => double.infinity,
                getTouchedSpotIndicator: (LineChartBarData barData, List<int> indicators) {
                  return indicators.map(
                    (int element) {
                      return TouchedSpotIndicatorData(const FlLine(color: Colors.red),
                          FlDotData(getDotPainter: (_, __, ___, ____) => FlDotCirclePainter(radius: 10)));
                    },
                  ).toList();
                },
                touchCallback: (data, response) {
                  if (data is FlTapUpEvent ||
                      data is FlTapCancelEvent ||
                      data is FlLongPressEnd ||
                      data is FlPanEndEvent) {
                    setState(() {
                      testList = originList;
                    });
                  } else if (response?.lineBarSpots != null) {
                    setState(() {
                      final updatedSpots = [...originList];
                      updatedSpots.removeRange(response!.lineBarSpots!.first.spotIndex + 1, updatedSpots.length);
                      testList = updatedSpots;
                    });
                  }
                },
              ),
              minY: 0,
              maxY: 1000,
              lineBarsData: [
                LineChartBarData(
                  color: Colors.grey,
                  spots: originList,
                ),
                LineChartBarData(
                  spots: testList,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}