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.
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.