How to drag and drop two existing points to form a new line in Flutter chart?

106 Views Asked by At

I have a line chart with existing points, now I want user can connect 2 points to draw a line. Example like in image expected output

I'm using syncfusion library. With it, I've manage to draw a new line by tapping on 2 points separately. Example like image current output

However, my client doesn't want that, they strictly want it to drag and drop like in the first image. Anyone have an idea or know any new library to achieve that?

My code:

class _MyHomePageState extends State<MyHomePage> {
  late List<ChartSampleData> firstData;
  late List<ChartSampleData> secondData;
  List<ChartSampleData> targetData = [];
  late ChartSeriesController _controller;
  int count = 0;
 
  @override
  void initState() {
    firstData = [
      ChartSampleData(01, 05),
      ChartSampleData(02, 10),
      ChartSampleData(03, 07),
      ChartSampleData(04, 02),
      ChartSampleData(05, 09),
      ChartSampleData(06, 01),
      ChartSampleData(07, 04),
      ChartSampleData(08, 06),
      ChartSampleData(09, 08),
      ChartSampleData(10, 03),
    ];
    secondData = [
      ChartSampleData(01, 15),
      ChartSampleData(02, 20),
      ChartSampleData(03, 17),
      ChartSampleData(04, 12),
      ChartSampleData(05, 19),
      ChartSampleData(06, 11),
      ChartSampleData(07, 14),
      ChartSampleData(08, 16),
      ChartSampleData(09, 18),
      ChartSampleData(10, 13),
    ];
    super.initState();
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SfCartesianChart(
        onDataLabelTapped: (onTapArgs) {
          count++;
          if (onTapArgs.seriesIndex == 0) {
            targetData.add(firstData[onTapArgs.pointIndex]);
          } else if (onTapArgs.seriesIndex == 1) {
            targetData.add(secondData[onTapArgs.pointIndex]);
          }
          if (count == 2) {
            count = 0;
            _controller.updateDataSource(addedDataIndexes: [
              targetData.length - 2,
              targetData.length - 1
            ]);
          }
        },
        primaryXAxis: NumericAxis(),
        primaryYAxis: NumericAxis(),
        series: <CartesianSeries<ChartSampleData, num>>[
          LineSeries(
            dataSource: firstData,
            xValueMapper: (ChartSampleData sales, int index) => sales.x,
            yValueMapper: (ChartSampleData sales, int index) => sales.y,
            color: Colors.blue,
            dataLabelSettings: DataLabelSettings(
              isVisible: true,
              labelAlignment: ChartDataLabelAlignment.middle,
              builder: (data, point, series, pointIndex, seriesIndex) {
                return Container(
                  height: 10,
                  width: 10,
                  decoration: const BoxDecoration(
                    shape: BoxShape.circle,
                    color: Colors.green,
                  ),
                );
              },
            ),
          ),
          LineSeries(
            dataSource: secondData,
            xValueMapper: (ChartSampleData sales, int index) => sales.x,
            yValueMapper: (ChartSampleData sales, int index) => sales.y,
            color: Colors.red,
            dataLabelSettings: DataLabelSettings(
              isVisible: true,
              labelAlignment: ChartDataLabelAlignment.middle,
              builder: (data, point, series, pointIndex, seriesIndex) {
                return Container(
                  height: 10,
                  width: 10,
                  decoration: const BoxDecoration(
                    shape: BoxShape.circle,
                    color: Colors.yellow,
                  ),
                );
              },
            ),
          ),
          LineSeries(
            dataSource: targetData,
            xValueMapper: (ChartSampleData sales, int index) => sales.x,
            yValueMapper: (ChartSampleData sales, int index) => sales.y,
            color: Colors.orange,
            onRendererCreated: (controller) {
              _controller = controller;
            },
            onCreateRenderer: (series) {
              return CustomLineSeriesRenderer();
            },
            dashArray: const [5, 5],
          ),
        ],
      ),
    );
  }
 
  @override
  void dispose() {
    targetData.clear();
    firstData.clear();
    secondData.clear();
    super.dispose();
  }
}
 
class CustomLineSeriesRenderer extends LineSeriesRenderer {
  @override
  LineSegment createSegment() {
    return CustomLineSegment();
  }
}
 
class CustomLineSegment extends LineSegment {
  @override
  void onPaint(Canvas canvas) {
    if (currentSegmentIndex! % 2 == 0) {
      super.onPaint(canvas);
    }
  }
}
0

There are 0 best solutions below