Is it possible to synchornize crosshair in multiple charts?

Hi, 

is it possible to synchronize crosshair across multiple charts?

Similarly to https://support.syncfusion.com/kb/article/10568/how-to-synchronize-trackball-in-multiple-flutter-sfcartesianchart- but with using CrosshairBehaviour instead of TrackballBehaviour.


1 Reply

LP Lokesh Palani Syncfusion Team November 23, 2023 01:11 PM UTC

Hi,


We have validated your query. You can achieve your requirement by using the onChartTouchInteractionMove property in the SfCartesianChart. We have prepared a sample to show the crosshairBehavior using the show method in the onChartTouchInteractionMove property with pixel. By using this method, you can synchronize the crosshairBehavior in multiple charts. We have also shared the user guide documentation, code snippet, and sample for your reference. Please let us know if you need any further details.


UG Link,

https://help.syncfusion.com/flutter/cartesian-charts/callbacks#oncharttouchinteractionup

https://help.syncfusion.com/flutter/cartesian-charts/trackball-crosshair#crosshair

https://help.syncfusion.com/flutter/cartesian-charts/methods#show-method-in-crosshairbehavior


Code Snippet:


import 'package:flutter/material.dart';

import 'package:syncfusion_flutter_charts/charts.dart';

 

void main() => runApp(const MyChart());

 

class MyChart extends StatelessWidget {

  const MyChart({super.key});

 

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      debugShowCheckedModeBanner: false,

      theme: ThemeData(

        primarySwatch: Colors.blue,

      ),

      home: const SynchronizedCrosshair(),

    );

  }

}

 

class SynchronizedCrosshair extends StatefulWidget {

  const SynchronizedCrosshair({Key? key}) : super(key: key);

 

  @override

  _SynchronizedCrosshairState createState() => _SynchronizedCrosshairState();

}

 

class _SynchronizedCrosshairState extends State<SynchronizedCrosshair> {

  @override

  Widget build(BuildContext context) {

    return const SafeArea(

      child: Scaffold(

        backgroundColor: Colors.white,

        body: SingleChildScrollView(

          scrollDirection: Axis.vertical,

          child: Column(

            children: <Widget>[

              SizedBox(

                height: 280,

                child: FirstChart(),

              ),

              SizedBox(

                height: 280,

                child: SecondChart(),

              ),

            ],

          ),

        ),

      ),

    );

  }

}

 

CrosshairBehavior _crossHair1 = CrosshairBehavior(

  enable: true,

  activationMode: ActivationMode.singleTap,

);

CrosshairBehavior _crossHair2 = CrosshairBehavior(

  enable: true,

  activationMode: ActivationMode.singleTap,

);

 

class FirstChart extends StatefulWidget {

  const FirstChart({super.key});

 

  @override

  State<StatefulWidget> createState() {

    return FirstChartState();

  }

}

 

class FirstChartState extends State<FirstChart> {

  @override

  Widget build(BuildContext context) {

    return SfCartesianChart(

      onChartTouchInteractionMove: (ChartTouchInteractionArgs args) {

        _crossHair2.show(args.position.dx, args.position.dy, 'pixel');

      },

      backgroundColor: Colors.white,

      primaryXAxis: CategoryAxis(),

      title: ChartTitle(text: 'Chart 1'),

      crosshairBehavior: _crossHair1,

      series: <LineSeries<SalesData, String>>[

        LineSeries<SalesData, String>(

          dataSource: <SalesData>[

            SalesData('Jan', 21),

            SalesData('Feb', 24),

            SalesData('Mar', 35),

            SalesData('Apr', 38),

            SalesData('May', 54),

            SalesData('Jun', 21),

            SalesData('Jul', 24),

            SalesData('Aug', 35),

            SalesData('Sep', 38),

            SalesData('Oct', 54),

            SalesData('Nov', 38),

            SalesData('Dec', 54)

          ],

          xValueMapper: (SalesData sales, _) => sales.year,

          yValueMapper: (SalesData sales, _) => sales.sales,

        ),

      ],

    );

  }

}

 

class SecondChart extends StatefulWidget {

  const SecondChart({super.key});

 

  @override

  State<StatefulWidget> createState() {

    return SecondChartState();

  }

}

 

class SecondChartState extends State<SecondChart> {

  @override

  Widget build(BuildContext context) {

    return SfCartesianChart(

      onChartTouchInteractionMove: (ChartTouchInteractionArgs args) {

        _crossHair1.show(args.position.dx, args.position.dy, 'pixel');

      },

      backgroundColor: Colors.white,

      primaryXAxis: CategoryAxis(),

      title: ChartTitle(text: 'Chart 2'),

      crosshairBehavior: _crossHair2,

      series: <LineSeries<SalesData, String>>[

        LineSeries<SalesData, String>(

          dataSource: <SalesData>[

            SalesData('Jan', 21),

            SalesData('Feb', 24),

            SalesData('Mar', 35),

            SalesData('Apr', 38),

            SalesData('May', 54),

            SalesData('Jun', 21),

            SalesData('Jul', 24),

            SalesData('Aug', 35),

            SalesData('Sep', 38),

            SalesData('Oct', 54),

            SalesData('Nov', 38),

            SalesData('Dec', 54)

          ],

          xValueMapper: (SalesData sales, _) => sales.year,

          yValueMapper: (SalesData sales, _) => sales.sales,

        ),

      ],

    );

  }

}

 

class SalesData {

  SalesData(this.year, this.sales);

 

  final String year;

  final double sales;

}


Regards,

Lokesh P.


Attachment: chart_185533_synchronize_crosshair_cb458201.zip

Loader.
Up arrow icon