paintBar method

  1. @override
void paintBar(
  1. ChartCanvas canvas,
  2. double animationPercent,
  3. Iterable<BarRendererElement<D>> barElements
)

Paints a stack of bar elements on the canvas.

Implementation

@override
void paintBar(
  ChartCanvas canvas,
  double animationPercent,
  Iterable<BarRendererElement<D>> barElements,
) {
  final bars = <CanvasRect>[];

  // When adjusting bars for stacked bar padding, do not modify the first bar
  // if rendering vertically and do not modify the last bar if rendering
  // horizontally.
  final unmodifiedBar =
      renderingVertically ? barElements.first : barElements.last;

  // Find the max bar width from each segment to calculate corner radius.
  var maxBarWidth = 0;

  var measureIsNegative = false;

  for (final bar in barElements) {
    var bounds = bar.bounds;

    measureIsNegative = measureIsNegative || bar.measureIsNegative!;

    if (bar != unmodifiedBar) {
      bounds = renderingVertically
          ? Rectangle<int>(
              bar.bounds!.left,
              max(
                0,
                bar.bounds!.top +
                    (measureIsNegative ? _stackedBarPaddingPx : 0),
              ),
              bar.bounds!.width,
              max(0, bar.bounds!.height - _stackedBarPaddingPx),
            )
          : Rectangle<int>(
              max(
                0,
                bar.bounds!.left +
                    (measureIsNegative ? _stackedBarPaddingPx : 0),
              ),
              bar.bounds!.top,
              max(0, bar.bounds!.width - _stackedBarPaddingPx),
              bar.bounds!.height,
            );
    }

    bars.add(
      CanvasRect(
        bounds!,
        dashPattern: bar.dashPattern,
        fill: bar.fillColor,
        pattern: bar.fillPattern,
        stroke: bar.color,
        strokeWidthPx: bar.strokeWidthPx,
      ),
    );

    maxBarWidth =
        max(maxBarWidth, renderingVertically ? bounds.width : bounds.height);
  }

  bool roundTopLeft;
  bool roundTopRight;
  bool roundBottomLeft;
  bool roundBottomRight;

  if (measureIsNegative) {
    // Negative bars should be rounded towards the negative axis direction.
    // In vertical mode, this is the bottom. In horizontal mode, this is the
    // left side of the chart for LTR, or the right side for RTL.
    roundTopLeft = !renderingVertically && !isRtl;
    roundTopRight = !renderingVertically && isRtl;
    roundBottomLeft = renderingVertically || !isRtl;
    roundBottomRight = renderingVertically || isRtl;
  } else {
    // Positive bars should be rounded towards the positive axis direction.
    // In vertical mode, this is the top. In horizontal mode, this is the
    // right side of the chart for LTR, or the left side for RTL.
    roundTopLeft = renderingVertically || isRtl;
    roundTopRight = !isRtl;
    roundBottomLeft = isRtl;
    roundBottomRight = !(renderingVertically || isRtl);
  }

  final barStack = CanvasBarStack(
    bars,
    radius: cornerStrategy.getRadius(maxBarWidth),
    stackedBarPadding: _stackedBarPaddingPx,
    roundTopLeft: roundTopLeft,
    roundTopRight: roundTopRight,
    roundBottomLeft: roundBottomLeft,
    roundBottomRight: roundBottomRight,
  );

  // If bar stack's range width is:
  // * Within the component bounds, then draw the bar stack.
  // * Partially out of component bounds, then clip the stack where it is out
  // of bounds.
  // * Fully out of component bounds, do not draw.

  final componentBounds = this.componentBounds!;
  final barOutsideBounds = renderingVertically
      ? barStack.fullStackRect.left < componentBounds.left ||
          barStack.fullStackRect.right > componentBounds.right
      : barStack.fullStackRect.top < componentBounds.top ||
          barStack.fullStackRect.bottom > componentBounds.bottom;

  // TODO: When we have initial viewport, add image test for
  // clipping.
  if (barOutsideBounds) {
    final clipBounds = _getBarStackBounds(barStack.fullStackRect);

    // Do not draw the bar stack if it is completely outside of the component
    // bounds.
    if (clipBounds.width <= 0 || clipBounds.height <= 0) {
      return;
    }

    canvas.setClipBounds(clipBounds);
  }

  canvas.drawBarStack(barStack, drawAreaBounds: componentBounds);

  if (barOutsideBounds) {
    canvas.resetClipBounds();
  }

  // Decorate the bar segments if there is a decorator.
  barRendererDecorator?.decorate(
    barElements,
    canvas,
    graphicsFactory!,
    drawBounds: drawBounds!,
    animationPercent: animationPercent,
    renderingVertically: renderingVertically,
    rtl: isRtl,
  );
}