Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class MyApp extends StatelessWidget {
'Selection',
];

MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
Expand All @@ -29,20 +31,19 @@ class MyApp extends StatelessWidget {
return ListTile(
title: Text(items[index]),
onTap: () {
String title = 'Synchronized ${items[index]}';
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Scaffold(
appBar: AppBar(
title: Text('$title'),
title: Text('Synchronized ${items[index]}'),
),
body: Center(
child: index == 0
? SynchronizedTrackball()
? const SynchronizedTrackball()
: index == 1
? SynchronizedZoomPan()
: SynchronizedSelection(),
? const SynchronizedZoomPan()
: const SynchronizedSelection(),
),
),
),
Expand Down
76 changes: 24 additions & 52 deletions lib/selection.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: must_be_immutable

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';

Expand All @@ -8,26 +10,10 @@ class SynchronizedSelection extends StatelessWidget {

@override
Widget build(BuildContext context) {
return const MaterialApp(
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Synchronized Selection',
home: MyHomePage(),
);
}
}

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

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return const SafeArea(
child: Scaffold(
home: Scaffold(
backgroundColor: Colors.white,
body: Row(
children: <Widget>[
Expand All @@ -40,12 +26,12 @@ class _MyHomePageState extends State<MyHomePage> {
}
}

SelectionBehavior selectionBehavior1 =
SelectionBehavior _baseSelection =
SelectionBehavior(enable: true, toggleSelection: false);
SelectionBehavior selectionBehavior2 =
SelectionBehavior _targetSelection =
SelectionBehavior(enable: true, toggleSelection: false);
int selectedIndex = -1;
List<SalesData> data = <SalesData>[
int _selectedIndex = -1;
List<SalesData> _data = <SalesData>[
SalesData('Jan', 21),
SalesData('Feb', 24),
SalesData('Mar', 35),
Expand All @@ -54,16 +40,9 @@ List<SalesData> data = <SalesData>[
SalesData('Jun', 21),
];

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

@override
State<StatefulWidget> createState() {
return FirstChartState();
}
}

class FirstChartState extends State<FirstChart> {
bool _isInteractive = false;

@override
Expand All @@ -73,37 +52,30 @@ class FirstChartState extends State<FirstChart> {
_isInteractive = true;
},
onSelectionChanged: (selectionArgs) {
if (_isInteractive && selectedIndex != selectionArgs.pointIndex) {
selectedIndex = selectionArgs.pointIndex;
selectionBehavior2.selectDataPoints(selectedIndex);
if (_isInteractive && _selectedIndex != selectionArgs.pointIndex) {
_selectedIndex = selectionArgs.pointIndex;
_targetSelection.selectDataPoints(_selectedIndex);
_isInteractive = false;
}
},
primaryXAxis: const CategoryAxis(),
title: const ChartTitle(text: 'Chart 1'),
series: <ColumnSeries<SalesData, String>>[
ColumnSeries<SalesData, String>(
dataSource: data,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.sales,
selectionBehavior: selectionBehavior1,
dataSource: _data,
xValueMapper: (SalesData sales, int index) => sales.year,
yValueMapper: (SalesData sales, int index) => sales.sales,
selectionBehavior: _baseSelection,
color: const Color.fromRGBO(99, 85, 199, 1),
),
],
);
}
}

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

@override
State<StatefulWidget> createState() {
return SecondChartState();
}
}
class SecondChart extends StatelessWidget {
SecondChart({super.key});

class SecondChartState extends State<SecondChart> {
bool _isInteractive = false;

@override
Expand All @@ -113,20 +85,20 @@ class SecondChartState extends State<SecondChart> {
_isInteractive = true;
},
onSelectionChanged: (selectionArgs) {
if (_isInteractive && selectedIndex != selectionArgs.pointIndex) {
selectedIndex = selectionArgs.pointIndex;
selectionBehavior1.selectDataPoints(selectedIndex);
if (_isInteractive && _selectedIndex != selectionArgs.pointIndex) {
_selectedIndex = selectionArgs.pointIndex;
_baseSelection.selectDataPoints(_selectedIndex);
_isInteractive = false;
}
},
primaryXAxis: const CategoryAxis(),
title: const ChartTitle(text: 'Chart 2'),
series: <ColumnSeries<SalesData, String>>[
ColumnSeries<SalesData, String>(
dataSource: data,
dataSource: _data,
xValueMapper: (SalesData sales, _) => sales.year,
yValueMapper: (SalesData sales, _) => sales.sales,
selectionBehavior: selectionBehavior2,
selectionBehavior: _targetSelection,
color: const Color.fromRGBO(99, 85, 199, 1),
),
],
Expand Down
79 changes: 25 additions & 54 deletions lib/trackball.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: must_be_immutable

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

Expand All @@ -11,26 +13,10 @@ class SynchronizedTrackball extends StatelessWidget {

@override
Widget build(BuildContext context) {
return const MaterialApp(
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Synchronized Trackball',
home: MyHomePage(),
);
}
}

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

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return const SafeArea(
child: Scaffold(
home: Scaffold(
backgroundColor: Colors.white,
body: Row(
children: <Widget>[
Expand All @@ -43,26 +29,18 @@ class _MyHomePageState extends State<MyHomePage> {
}
}

TrackballBehavior trackball1 =
TrackballBehavior _baseTrackball =
TrackballBehavior(enable: true, activationMode: ActivationMode.singleTap);
TrackballBehavior trackball2 =
TrackballBehavior _targetTrackball =
TrackballBehavior(enable: true, activationMode: ActivationMode.singleTap);

ChartSeriesController? _controller1;
ChartSeriesController? _controller2;
DataModel dataModel = DataModel();
ChartSeriesController? _baseSeriesController;
ChartSeriesController? _targetSeriesController;
DataModel _dataModel = DataModel();
Offset? _position;

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

@override
State<StatefulWidget> createState() {
return FirstChartState();
}
}
class FirstChart extends StatelessWidget {
FirstChart({super.key});

class FirstChartState extends State<FirstChart> {
bool _isInteractive = false;

@override
Expand All @@ -73,14 +51,14 @@ class FirstChartState extends State<FirstChart> {
},
onChartTouchInteractionUp: (ChartTouchInteractionArgs tapArgs) {
_isInteractive = false;
trackball2.hide();
_targetTrackball.hide();
},
onTrackballPositionChanging: (TrackballArgs trackballArgs) {
if (_isInteractive) {
_position = _controller1!.pointToPixel(
_position = _baseSeriesController!.pointToPixel(
trackballArgs.chartPointInfo.chartPoint!,
);
trackball2.show(_position!.dx, _position!.dy, 'pixel');
_targetTrackball.show(_position!.dx, _position!.dy, 'pixel');
}
},
primaryXAxis: DateTimeAxis(
Expand All @@ -96,32 +74,25 @@ class FirstChartState extends State<FirstChart> {
interval: 0.025,
),
title: const ChartTitle(text: 'Chart 1'),
trackballBehavior: trackball1,
trackballBehavior: _baseTrackball,
series: <LineSeries<SalesData, DateTime>>[
LineSeries<SalesData, DateTime>(
color: const Color.fromRGBO(99, 85, 199, 1),
dataSource: dataModel.data,
dataSource: _dataModel.data,
xValueMapper: (SalesData sales, int index) => sales.dateTime,
yValueMapper: (SalesData sales, int index) => sales.y,
onRendererCreated: (ChartSeriesController controller) {
_controller2 = controller;
_targetSeriesController = controller;
},
),
],
);
}
}

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

@override
State<StatefulWidget> createState() {
return SecondChartState();
}
}
class SecondChart extends StatelessWidget {
SecondChart({super.key});

class SecondChartState extends State<SecondChart> {
bool _isInteractive = false;

@override
Expand All @@ -132,14 +103,14 @@ class SecondChartState extends State<SecondChart> {
},
onChartTouchInteractionUp: (ChartTouchInteractionArgs tapArgs) {
_isInteractive = false;
trackball1.hide();
_baseTrackball.hide();
},
onTrackballPositionChanging: (TrackballArgs trackballArgs) {
if (_isInteractive) {
_position = _controller2!.pointToPixel(
_position = _targetSeriesController!.pointToPixel(
trackballArgs.chartPointInfo.chartPoint!,
);
trackball1.show(_position!.dx, _position!.dy, 'pixel');
_baseTrackball.show(_position!.dx, _position!.dy, 'pixel');
}
},
primaryXAxis: DateTimeAxis(
Expand All @@ -155,15 +126,15 @@ class SecondChartState extends State<SecondChart> {
interval: 0.025,
),
title: const ChartTitle(text: 'Chart 2'),
trackballBehavior: trackball2,
trackballBehavior: _targetTrackball,
series: <LineSeries<SalesData, DateTime>>[
LineSeries<SalesData, DateTime>(
color: const Color.fromRGBO(99, 85, 199, 1),
dataSource: dataModel.data,
dataSource: _dataModel.data,
xValueMapper: (SalesData sales, int index) => sales.dateTime,
yValueMapper: (SalesData sales, int index) => sales.y,
onRendererCreated: (ChartSeriesController controller) {
_controller1 = controller;
_baseSeriesController = controller;
},
),
],
Expand Down
Loading