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.87k stars 1.78k forks source link

Vertical Line Configuration? #1522

Closed marc-wilson closed 11 months ago

marc-wilson commented 11 months ago

I'm not seeing any way to do this, but I want more control over the display of the vertical line and bubble.

I just want the line. I don't want the bubble or tooltip. I managed to "hide" the tooltip by making all the colors transparent.

Unfortunately, I am not seeing any configuration around the line or bubble, only the physical tooltip.

https://github.com/imaNNeo/fl_chart/blob/master/repo_files/documentations/line_chart.md#linetouchdata-read-about-touch-handling

image image

It would be nice to be able to control the vertical line width and color.

marc-wilson commented 11 months ago

Co-pilot told me how to do it... not very intuitive, but it works. Is there a better solution than just making everything transparent in color to "hide" it?


                      getTouchedSpotIndicator: (barData, spotIndexes) {
                        return spotIndexes.map((spotIndex) {
                          final FlSpot spot = barData.spots[spotIndex];
                          if (spot.x == 0 || spot.x == barData.spots.length - 1)
                            return null;
                          return TouchedSpotIndicatorData(
                            const FlLine(
                              color: Colors.white,
                              strokeWidth: 1,
                            ),
                            FlDotData(
                              show: true,
                              getDotPainter: (spot, percent, barData, index) {
                                return FlDotCirclePainter(
                                  radius: 4,
                                  color: Colors.transparent,
                                  strokeWidth: 1,
                                  strokeColor: Colors.transparent,
                                );
                              },
                            ),
                          );
                        }).toList();
                      },
translibrius commented 11 months ago

@marc-wilson Hey you can set handleBuiltInTouches to false, which will not draw anything associated with touch events. Then you can build your custom functionality by listening to the events. Heres how I do it:

LineTouchData getLineTouchData() {
    return LineTouchData(
      touchTooltipData: LineTouchTooltipData(
        tooltipBgColor: Colors.blueGrey.withOpacity(0.8),
        tooltipMargin: 100,
      ),
      touchCallback: (FlTouchEvent event, LineTouchResponse? response) {
        if (response == null || response.lineBarSpots == null) {
          return;
        }
        final index = response.lineBarSpots!.first.spotIndex;

        if (event is FlPanStartEvent) {
          ref.read(signalChartProvider.notifier).startDrag(index);
        } else if (event is FlPanUpdateEvent) {
          ref.read(signalChartProvider.notifier).updateDrag(index);
          ref.read(signalChartProvider.notifier).toggleSpotSelectionDuringDrag(index);
        } else if (event is FlPanEndEvent) {
          ref.read(signalChartProvider.notifier).endDrag();
        } else if (event is FlTapUpEvent) {
          ref.read(signalChartProvider.notifier).toggleSpotSelection(index);
        } else if (event is FlPointerHoverEvent) {
          ref.read(signalChartProvider.notifier).updateHover(index);
        } else if (event is FlPointerExitEvent) {
          ref.read(signalChartProvider.notifier).updateHover(-1);
        }
      },
      handleBuiltInTouches: false,
    );
  }

Then I would manually draw the vertical lines as ExtraLinesData:

ExtraLinesData getExtraLinesData(SignalChartState state) {
    return ExtraLinesData(
      extraLinesOnTop: true,
      verticalLines: [
        if (state.dragStartIndex != null)
          VerticalLine(
            x: state.dragStartIndex!.toDouble(),
            color: Colors.black,
            strokeWidth: 2,
          ),
        if (state.hoverIndex != null)
          VerticalLine(
            x: state.hoverIndex!.toDouble(),
            color: Colors.black,
            strokeWidth: 2,
          ),
      ],
    );
  }

P.S Keep in mind I'm using riverbud for updating the widget, but you can use setState() instead if you don't :)

imaNNeo commented 11 months ago

@translibrius's solution works