diff --git a/example/lib/radar_chart/samples/radar_chart_sample1.dart b/example/lib/radar_chart/samples/radar_chart_sample1.dart index 4177925e1..2e3c61f14 100644 --- a/example/lib/radar_chart/samples/radar_chart_sample1.dart +++ b/example/lib/radar_chart/samples/radar_chart_sample1.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; @@ -7,6 +9,8 @@ class RadarChartSample extends StatefulWidget { } class _RadarChartSampleState extends State { + int touchedDataSetIndex = -1; + @override Widget build(BuildContext context) { return AspectRatio( @@ -15,22 +19,34 @@ class _RadarChartSampleState extends State { color: Colors.white, child: RadarChart( RadarChartData( - titleCount: 3, - fillColor: Colors.grey, - dataSets: showingDataSets(), - tickCount: 4, - getTitle: (index) => '$index + values', - gridData: const BorderSide(color: Colors.black, width: 1.5), - titlePositionPercentageOffset: 0.3, - ticksTextStyle: const TextStyle( - color: Colors.deepPurple, - fontSize: 10, - ), - titleTextStyle: const TextStyle( - color: Colors.blue, - fontSize: 14, - ), - ), + titleCount: 3, + fillColor: Colors.grey, + dataSets: showingDataSets(), + tickCount: 4, + getTitle: (index) => '$index + values', + gridData: const BorderSide(color: Colors.black, width: 1.5), + titlePositionPercentageOffset: 0.3, + ticksTextStyle: const TextStyle( + color: Colors.deepPurple, + fontSize: 10, + ), + titleTextStyle: const TextStyle( + color: Colors.blue, + fontSize: 14, + ), + radarTouchData: RadarTouchData(touchCallback: (response) { + setState(() { + log('response type: ${response.touchInput}'); + + if (response.touchedSpot != null && + response.touchInput is! FlPanEnd && + response.touchInput is! FlLongPressEnd) { + touchedDataSetIndex = response?.touchedSpot?.touchedDataSetIndex ?? -1; + } else { + touchedDataSetIndex = -1; + } + }); + })), ), ), ); @@ -38,23 +54,25 @@ class _RadarChartSampleState extends State { List showingDataSets() { return [ - const RadarDataSet( + RadarDataSet( dataEntries: [ - RadarEntry(value: 5), - RadarEntry(value: 28), - RadarEntry(value: 25), + const RadarEntry(value: 5), + const RadarEntry(value: 28), + const RadarEntry(value: 25), ], borderWidth: 3, color: Colors.red, + entryRadius: (touchedDataSetIndex == 0) ? 6.0 : 3.0, ), - const RadarDataSet( + RadarDataSet( dataEntries: [ - RadarEntry(value: 18), - RadarEntry(value: 20), - RadarEntry(value: 30), + const RadarEntry(value: 18), + const RadarEntry(value: 20), + const RadarEntry(value: 30), ], borderWidth: 3, color: Colors.orange, + entryRadius: (touchedDataSetIndex == 1) ? 6.0 : 3.0, ), ]; } diff --git a/lib/src/chart/radar_chart/radar_chart.dart b/lib/src/chart/radar_chart/radar_chart.dart index 7e098c8b0..b1a0a85af 100644 --- a/lib/src/chart/radar_chart/radar_chart.dart +++ b/lib/src/chart/radar_chart/radar_chart.dart @@ -1,4 +1,5 @@ import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart'; +import 'package:fl_chart/src/chart/base/base_chart/touch_input.dart'; import 'package:fl_chart/src/chart/radar_chart/radar_chart_data.dart'; import 'package:fl_chart/src/chart/radar_chart/radar_chart_painter.dart'; import 'package:fl_chart/src/utils/utils.dart'; @@ -15,7 +16,6 @@ class RadarChart extends StatefulWidget { } //ToDo(payam) : handle animation -//ToDo(payam) : handle touch class _RadarChartState extends State { /// we handle under the hood animations (implicit animations) via this tween, /// it lerps between the old [PieChartData] to the new one. @@ -29,20 +29,124 @@ class _RadarChartState extends State { @override Widget build(BuildContext context) { - return CustomPaint( - key: _chartKey, - size: getDefaultSize(context), - painter: RadarChartPainter( - widget.data, - //ToDo(payam) : update it for animations - widget.data, - (touchHandler) { - setState(() { - _touchHandler = touchHandler; - }); - }, - textScale: MediaQuery.of(context).textScaleFactor, + final showingData = _getDate(); + final touchData = showingData.radarTouchData; + + return GestureDetector( + onLongPressStart: (d) { + final Size chartSize = _getChartSize(); + if (chartSize == null) return; + + final RadarTouchResponse response = _touchHandler?.handleTouch( + FlLongPressStart(d.localPosition), + chartSize, + ); + + if (_canHandleTouch(response, touchData)) touchData.touchCallback(response); + }, + onLongPressEnd: (d) { + final Size chartSize = _getChartSize(); + if (chartSize == null) return; + + final RadarTouchResponse response = _touchHandler?.handleTouch( + FlLongPressEnd(d.localPosition), + chartSize, + ); + + if (_canHandleTouch(response, touchData)) touchData.touchCallback(response); + }, + onLongPressMoveUpdate: (d) { + final Size chartSize = _getChartSize(); + if (chartSize == null) return; + + final RadarTouchResponse response = _touchHandler?.handleTouch( + FlLongPressMoveUpdate(d.localPosition), + chartSize, + ); + + if (_canHandleTouch(response, touchData)) touchData.touchCallback(response); + }, + onPanCancel: () { + final Size chartSize = _getChartSize(); + if (chartSize == null) return; + + final RadarTouchResponse response = _touchHandler?.handleTouch( + FlPanEnd(Offset.zero, const Velocity(pixelsPerSecond: Offset.zero)), + chartSize, + ); + + if (_canHandleTouch(response, touchData)) touchData.touchCallback(response); + }, + onPanEnd: (DragEndDetails details) { + final Size chartSize = _getChartSize(); + if (chartSize == null) { + return; + } + + final response = + _touchHandler?.handleTouch(FlPanEnd(Offset.zero, details.velocity), chartSize); + if (_canHandleTouch(response, touchData)) { + touchData.touchCallback(response); + } + }, + onPanDown: (DragDownDetails details) { + final Size chartSize = _getChartSize(); + if (chartSize == null) { + return; + } + + final response = _touchHandler?.handleTouch(FlPanStart(details.localPosition), chartSize); + if (_canHandleTouch(response, touchData)) { + touchData.touchCallback(response); + } + }, + onPanUpdate: (DragUpdateDetails details) { + final Size chartSize = _getChartSize(); + if (chartSize == null) { + return; + } + + final response = + _touchHandler?.handleTouch(FlPanMoveUpdate(details.localPosition), chartSize); + if (_canHandleTouch(response, touchData)) { + touchData.touchCallback(response); + } + }, + child: CustomPaint( + key: _chartKey, + size: getDefaultSize(context), + painter: RadarChartPainter( + widget.data, + //ToDo(payam) : update it for animations + widget.data, + (touchHandler) { + setState(() { + _touchHandler = touchHandler; + }); + }, + textScale: MediaQuery.of(context).textScaleFactor, + ), ), ); } + + RadarChartData _getDate() { + return widget.data; + } + + Size _getChartSize() { + if (_chartKey.currentContext != null) { + final RenderBox containerRenderBox = _chartKey.currentContext.findRenderObject(); + if (containerRenderBox.hasSize) { + return containerRenderBox.size; + } + return null; + } else { + return null; + } + } + + bool _canHandleTouch(RadarTouchResponse response, RadarTouchData touchData) { + return response != null && touchData != null && touchData.touchCallback != null; + } } diff --git a/lib/src/chart/radar_chart/radar_chart_painter.dart b/lib/src/chart/radar_chart/radar_chart_painter.dart index fddbe6d4a..4010fac8d 100644 --- a/lib/src/chart/radar_chart/radar_chart_painter.dart +++ b/lib/src/chart/radar_chart/radar_chart_painter.dart @@ -19,7 +19,7 @@ class RadarChartPainter extends BaseChartPainter RadarChartData data, RadarChartData targetData, Function(TouchHandler) touchHandler, { - double textScale, + double textScale =1 , }) : _backgroundPaint = Paint() ..color = data.fillColor ..style = PaintingStyle.fill @@ -169,7 +169,6 @@ class RadarChartPainter extends BaseChartPainter } void drawDataSets(Size size, Canvas canvas) { - // we will use dataSetsPosition to draw the graphs dataSetsPosition.asMap().forEach((index, dataSetOffset) { final graph = data.dataSets[index]; @@ -222,7 +221,7 @@ class RadarChartPainter extends BaseChartPainter @override RadarTouchResponse handleTouch(FlTouchInput touchInput, Size size) { - final touchedSpot = _getNearestTouchSpot(size, touchInput.getOffset(), null); + final touchedSpot = _getNearestTouchSpot(size, touchInput.getOffset(), dataSetsPosition); return RadarTouchResponse(touchedSpot, touchInput); } @@ -231,6 +230,25 @@ class RadarChartPainter extends BaseChartPainter Offset touchedPoint, List radarDataSetsPosition, ) { + for (int i = 0; i < radarDataSetsPosition.length; i++) { + final dataSetPosition = radarDataSetsPosition[i]; + for (int j = 0; j < dataSetPosition.entriesOffset.length; j++) { + final entryOffset = dataSetPosition.entriesOffset[j]; + if ((touchedPoint.dx - entryOffset.dx).abs() <= + targetData.radarTouchData.touchSpotThreshold && + (touchedPoint.dy - entryOffset.dy).abs() <= + targetData.radarTouchData.touchSpotThreshold) { + return RadarTouchedSpot( + targetData.dataSets[i], + i, + targetData.dataSets[i].dataEntries[j], + j, + FlSpot(entryOffset.dx, entryOffset.dy), + entryOffset, + ); + } + } + } return null; }