findBar static method

ChartInteractionResult? findBar(
  1. Offset tapPosition,
  2. List<ChartDataSet> dataSets,
  3. Size chartSize,
  4. double minX,
  5. double maxX,
  6. double minY,
  7. double maxY,
  8. double barWidth,
)

Find bar at tap location (optimized with early exit).

Searches through all data sets to find the bar containing the tap position. Uses efficient bounds checking and coordinate conversion.

Parameters:

  • tapPosition - The position where the user tapped
  • dataSets - List of chart data sets to search through
  • chartSize - Size of the chart area
  • minX, maxX, minY, maxY - Data bounds for coordinate conversion
  • barWidth - Width of each bar in canvas coordinates

Returns a ChartInteractionResult if a bar is found, null otherwise.

Implementation

static ChartInteractionResult? findBar(
  Offset tapPosition,
  List<ChartDataSet> dataSets,
  Size chartSize,
  double minX,
  double maxX,
  double minY,
  double maxY,
  double barWidth,
) {
  // Early exit if no data
  if (dataSets.isEmpty) return null;

  // Validate inputs using helper methods
  if (!_isValidSize(chartSize) ||
      !_isValidPosition(tapPosition) ||
      !_isValidBounds(minX, maxX, minY, maxY) ||
      !_isValidPositiveValue(barWidth) ||
      !_isValidPositiveValue(maxY)) {
    return null;
  }

  final xRange = maxX - minX;
  if (xRange == 0 || !xRange.isFinite) return null;

  // Pre-calculate half bar width and cache chart height
  final halfBarWidth = barWidth / 2;
  final chartHeight = chartSize.height;

  for (int dsIndex = 0; dsIndex < dataSets.length; dsIndex++) {
    final dataSet = dataSets[dsIndex];
    final point = dataSet.dataPoint;

    // Validate point values
    if (!_isValidPoint(point)) continue;

    // Calculate bar horizontal position
    final canvasX = ((point.x - minX) / xRange) * chartSize.width;
    if (!canvasX.isFinite) continue;

    // Early exit if tap is clearly to the left or right of bar
    if (tapPosition.dx < canvasX - halfBarWidth ||
        tapPosition.dx > canvasX + halfBarWidth) {
      continue;
    }

    // Calculate bar vertical position
    final barHeight = (point.y / maxY) * chartHeight;
    if (!barHeight.isFinite) continue;

    final barY = chartHeight - barHeight;
    if (!barY.isFinite) continue;

    // Check if tap is within bar vertical bounds
    if (tapPosition.dy >= barY && tapPosition.dy <= chartHeight) {
      return ChartInteractionResult(
        point: point,
        datasetIndex: dsIndex,
        elementIndex: 0,
        isHit: true,
      );
    }
  }

  return null;
}