draw method

  1. @override
void draw(
  1. Canvas canvas,
  2. Size size,
  3. ChartContext context
)
override

Implementation

@override
void draw(Canvas canvas, Size size, ChartContext context) {
  final series = context.config.series.isNotEmpty
      ? context.config.series.first
      : null;
  if (series == null || series.points.isEmpty) return;

  final stages = _orderedStages(series.points, sortDescending);
  final indexByPoint = {
    for (var i = 0; i < series.points.length; i++) series.points[i]: i,
  };
  final maxValue = stages.fold<double>(0, (m, p) => math.max(m, p.y.abs()));
  if (maxValue == 0) return;

  final anim = context.animationValue;
  final art = SeriesPaint(context.config.style);
  final bounds = context.bounds;
  final stageHeight =
      (bounds.height - gap * (stages.length - 1)) / stages.length;
  final maxWidth = bounds.width * 0.9;

  if (context.config.showGrid) {
    final gridPaint = context.paintCache.get(
      key: 'funnel-grid',
      color: context.theme.gridColor,
      strokeWidth: context.theme.gridStrokeWidth,
    );
    for (var g = 0; g <= stages.length; g++) {
      final y = bounds.top + g * (stageHeight + gap);
      canvas.drawLine(
        Offset(bounds.left, y),
        Offset(bounds.right, y),
        gridPaint,
      );
    }
  }

  for (var i = 0; i < stages.length; i++) {
    final point = stages[i];
    final value = point.y.abs() * anim;
    final widthTop = i == 0
        ? maxWidth * (value / maxValue)
        : maxWidth * (stages[i - 1].y.abs() / maxValue);
    final widthBottom = maxWidth * (value / maxValue);

    final top = bounds.top + i * (stageHeight + gap);
    final bottom = top + stageHeight;
    final centerX = bounds.center.dx;

    final path = Path()
      ..moveTo(centerX - widthTop / 2, top)
      ..lineTo(centerX + widthTop / 2, top)
      ..lineTo(centerX + widthBottom / 2, bottom)
      ..lineTo(centerX - widthBottom / 2, bottom)
      ..close();

    final color = series.style.color ?? context.theme.seriesColor(i);
    canvas.drawPath(
      path,
      art.barFill(
        Rect.fromLTRB(centerX - widthTop / 2, top, centerX + widthTop / 2, bottom),
        color,
        opacity: 0.92,
      ),
    );

    if (context.hoveredHit?.pointIndex == indexByPoint[point]) {
      canvas.drawPath(
        path,
        context.paintCache.get(
          key: 'funnel-hover-$i',
          color: context.theme.crosshairColor,
          strokeWidth: 2,
        ),
      );
    }

    if (labelStages || context.config.showAxis) {
      _drawLabel(canvas, context, point, centerX, top + stageHeight / 2);
    }
  }

  AxisEngine.drawAxisTitles(canvas, context);
}