chartSvg function

String chartSvg(
  1. ReportElement chart,
  2. Map<String, dynamic> data
)

Generates a self-contained SVG, which remains vector graphics in the PDF.

Implementation

String chartSvg(ReportElement chart, Map<String, dynamic> data) {
  final points = chartData(chart, data);
  final width = chart.width.clamp(1, 10000);
  final height = chart.height.clamp(1, 10000);
  if (points.isEmpty) {
    return '<svg xmlns="http://www.w3.org/2000/svg" width="$width" height="$height"/>';
  }
  String color(int index) =>
      '#${(chart.chartColors[index % chart.chartColors.length] & 0xffffff).toRadixString(16).padLeft(6, '0')}';
  String esc(String value) => value
      .replaceAll('&', '&amp;')
      .replaceAll('<', '&lt;')
      .replaceAll('>', '&gt;');
  final content = StringBuffer();
  final max = points
      .map((point) => point.$2.abs())
      .fold<double>(0, (a, b) => a > b ? a : b);
  final plotHeight = height - (chart.chartShowLabels ? 28 : 8);
  if (chart.chartType == ChartType.pie) {
    final total = points.fold<double>(0, (sum, point) => sum + point.$2.abs());
    final radius = (width < plotHeight ? width : plotHeight) * .4;
    final cx = width / 2, cy = plotHeight / 2;
    var angle = -1.57079632679;
    for (final entry in points.indexed) {
      final sweep = total == 0 ? 0 : entry.$2.$2.abs() / total * 6.28318530718;
      final x1 = cx + radius * math.cos(angle), y1 = cy + radius * math.sin(angle);
      final x2 = cx + radius * math.cos(angle + sweep),
          y2 = cy + radius * math.sin(angle + sweep);
      final large = sweep > 3.14159265359 ? 1 : 0;
      content.write(
        '<path d="M $cx $cy L $x1 $y1 A $radius $radius 0 $large 1 $x2 $y2 Z" fill="${color(entry.$1)}"/>',
      );
      angle += sweep;
    }
  } else {
    final slot = width / points.length;
    final coords = <String>[];
    for (final entry in points.indexed) {
      final x = slot * entry.$1 + slot / 2;
      final y =
          plotHeight -
          (max == 0 ? 0 : entry.$2.$2.abs() / max * (plotHeight - 8));
      if (chart.chartType == ChartType.bar) {
        content.write(
          '<rect x="${x - slot * .32}" y="$y" width="${slot * .64}" height="${plotHeight - y}" fill="${color(entry.$1)}"/>',
        );
      } else {
        coords.add('$x,$y');
        content.write(
          '<circle cx="$x" cy="$y" r="3" fill="${color(entry.$1)}"/>',
        );
      }
      if (chart.chartShowLabels) {
        content.write(
          '<text x="$x" y="${height - 8}" text-anchor="middle" font-size="9">${esc(entry.$2.$1)}</text>',
        );
      }
    }
    if (coords.isNotEmpty) {
      content.write(
        '<polyline points="${coords.join(' ')}" fill="none" stroke="${color(0)}" stroke-width="2"/>',
      );
    }
  }
  return '<svg xmlns="http://www.w3.org/2000/svg" width="$width" height="$height">$content</svg>';
}