barChart static method

String barChart({
  1. required List<double> values,
  2. required List<String> labels,
  3. double width = 400,
  4. double height = 250,
  5. List<String>? colors,
  6. String title = '',
})

Generate a bar chart SVG.

Implementation

static String barChart({
  required List<double> values,
  required List<String> labels,
  double width = 400,
  double height = 250,
  List<String>? colors,
  String title = '',
}) {
  if (values.isEmpty) return _emptySvg(width, height);
  final buf = StringBuffer();
  final maxV = values.reduce((a, b) => a > b ? a : b);
  const padLeft = 40.0, padBottom = 30.0, padTop = 30.0, padRight = 10.0;
  final chartW = width - padLeft - padRight;
  final chartH = height - padTop - padBottom;
  final barW = chartW / values.length;

  buf.writeln(
    '<svg xmlns="http://www.w3.org/2000/svg" width="$width" height="$height">',
  );
  if (title.isNotEmpty) {
    buf.writeln(
      '<text x="${width / 2}" y="16" text-anchor="middle" font-size="14" font-weight="bold" fill="#1a1a1a">$title</text>',
    );
  }

  // Grid lines (5 horizontal).
  for (int i = 0; i <= 5; i++) {
    final y = padTop + chartH - (i / 5) * chartH;
    final label = (maxV * i / 5).toStringAsFixed(0);
    buf.writeln(
      '<line x1="$padLeft" y1="$y" x2="${width - padRight}" y2="$y" '
      'stroke="#e0e0e0" stroke-width="0.5"/>',
    );
    buf.writeln(
      '<text x="${padLeft - 4}" y="${y + 4}" text-anchor="end" '
      'font-size="9" fill="#666">$label</text>',
    );
  }

  // Bars.
  for (int i = 0; i < values.length; i++) {
    final barH = maxV > 0 ? (values[i] / maxV) * chartH : 0;
    final x = padLeft + i * barW + barW * 0.1;
    final y = padTop + chartH - barH;
    final color = colors != null && i < colors.length
        ? colors[i]
        : _defaultColors[i % _defaultColors.length];
    buf.writeln(
      '<rect x="${x.toStringAsFixed(1)}" y="${y.toStringAsFixed(1)}" '
      'width="${(barW * 0.8).toStringAsFixed(1)}" '
      'height="${barH.toStringAsFixed(1)}" fill="$color" rx="2"/>',
    );
    if (i < labels.length) {
      final lx = padLeft + i * barW + barW / 2;
      buf.writeln(
        '<text x="${lx.toStringAsFixed(1)}" y="${(height - padBottom + 12).toStringAsFixed(1)}" '
        'text-anchor="middle" font-size="9" fill="#444">${labels[i]}</text>',
      );
    }
  }

  buf.writeln('</svg>');
  return buf.toString();
}