findBar static method
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 tappeddataSets- List of chart data sets to search throughchartSize- Size of the chart areaminX,maxX,minY,maxY- Data bounds for coordinate conversionbarWidth- 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;
}