imaNNeo / fl_chart

FL Chart is a highly customizable Flutter chart library that supports Line Chart, Bar Chart, Pie Chart, Scatter Chart, and Radar Chart.
https://flchart.dev
MIT License
6.76k stars 1.75k forks source link

Feature Request - add support for scale gesture recognition for LineTouchData.touchCallback #1720

Open eladm-ultrawis opened 2 months ago

eladm-ultrawis commented 2 months ago

I thoroughly investigated a solution for supporting scale and panning of a line plot by manipulating minX and minY. I mostly followed the suggestions offered in this open issue.

After trying many of the offered solutions and a few of my own I reached the following conclusions:

  1. supporting panning of a plot is best done using LineTouchData.touchCallback and handling FlPanUpdateEvent.
  2. supporting zoom is very hard to do: using a GestureDetector / Listener only seems to work properly if my FlChart is warpped in an IgnorePointer widget. and unfortunately LineTouchData.touchCallback does not support scale events.

I forked fl_chart and tried to add a ScaleGestureRecognizer to RenderBaseChart and added a bunch of Fl***Events for scale events. I followed the usage pattern for the other gesture recognizers however this doesn't work.

Could you advice on how this should be added?

Here is the essence of what I tried to add in render_base_chart.dart:

  void initGestureRecognizers() {
    _scaleGestureRecognizer = ScaleGestureRecognizer()
      ..onStart = (details) {
        _notifyTouchEvent(FlScaleStartEvent(details));
      }
      ..onUpdate = (details) {
        _notifyTouchEvent(FlScaleUpdateEvent(details));
      }
      ..onEnd = (details) {
        _notifyTouchEvent(FlScaleEndEvent(details));
      };

and here:

  @override
  void handleEvent(PointerEvent event, covariant BoxHitTestEntry entry) {
    assert(debugHandleEvent(event, entry));
    if (_touchCallback == null) {
      return;
    }
    if (event is PointerDownEvent) {
      _longPressGestureRecognizer.addPointer(event);
      _tapGestureRecognizer.addPointer(event);
      _panGestureRecognizer.addPointer(event);
      _scaleGestureRecognizer.addPointer(event);
    } else if (event is PointerHoverEvent) {
      _notifyTouchEvent(FlPointerHoverEvent(event));
    }
  }
eladm-ultrawis commented 2 months ago

Ok, Apparently the ScaleGestureRecognizer starts working if it replaces the PanGestureRecognizer entirely. I think that we should add a flag to LineTouchData indicating if the user wishes to detect scale gesture. in this case we will use a ScaleGestureRecognizer instead of PanGestureRecognizer.

@imaNNeo could you please advise? what do you think?

Tobbyte commented 1 month ago

yup ScaleGestureRecognizer and PanGestureRecognizer don't like to be put together. Solution for me was to check for the pointerCount: when only one, use details.focalPointDelta.dx to effectively get the panRecognizer. With this, your https://github.com/imaNNeo/fl_chart/pull/1721 restriction "enabling scale detection and pan gesture detection is not supported" is not longer, dito the need for switching between pan and scale.