save_points_chart

A modern Flutter charting library with canvas-based rendering, Material 3–friendly themes, smooth animations, and zero third-party runtime dependencies (Flutter SDK only).

pub package License

Features

  • 15+ chart types — line, bar, area, pie/donut, scatter, radar, gauge, sparkline, stacked area, waterfall, funnel, bubble, heatmap, candlestick, and timeline
  • Unified API — every chart uses ChartConfig + a typed widget (LineChart, BarChart, …)
  • Interactions — tooltips, crosshair, tap selection, pinch zoom & pan (where applicable)
  • ThemingChartTheme.light(), ChartTheme.dark(), ChartTheme.dashboard(), or fully custom colors
  • TemplatesChartTemplateStyle.dashboard (title, legend, grid) or plain (minimal chrome)
  • Animations — configurable duration and curve tension for smooth line/area transitions
  • Export — snapshot charts as PNG; optional PDF reports via ChartWidgetController / ChartCard
  • AccessibilitysemanticLabel on ChartConfig for screen readers
  • Extensible engine — layer stack, render pipeline, and ChartRenderer plugins for custom charts

Installation

Add to pubspec.yaml:

dependencies:
  save_points_chart: ^1.9.1

Import the public API:

import 'package:save_points_chart/save_points_charts.dart';

Quick start

import 'package:flutter/material.dart';
import 'package:save_points_chart/save_points_charts.dart';

class TrafficChart extends StatelessWidget {
  const TrafficChart({super.key});

  @override
  Widget build(BuildContext context) {
    final config = ChartConfig(
      title: 'Traffic trend',
      subtitle: 'Desktop vs mobile',
      xAxisTitle: 'Month',
      yAxisTitle: 'Users',
      showLegend: true,
      template: ChartTemplateStyle.dashboard,
      series: [
        ChartSeries(
          id: 'desktop',
          name: 'Desktop',
          points: const [
            ChartPoint(x: 0, y: 220, label: 'Jan'),
            ChartPoint(x: 1, y: 260, label: 'Feb'),
            ChartPoint(x: 2, y: 240, label: 'Mar'),
          ],
        ),
        ChartSeries(
          id: 'mobile',
          name: 'Mobile',
          points: const [
            ChartPoint(x: 0, y: 140, label: 'Jan'),
            ChartPoint(x: 1, y: 180, label: 'Feb'),
            ChartPoint(x: 2, y: 200, label: 'Mar'),
          ],
        ),
      ],
    );

    return SizedBox(
      height: 280,
      child: LineChart(config: config),
    );
  }
}

Chart types

Widget Description Notable options
LineChart Cartesian line series LineChartMode.straight / smooth, fillArea
BarChart Vertical or horizontal bars BarChartOrientation, BarChartLayout.grouped / stacked
AreaChart Filled area under lines Shares line renderer with fill
PieChart Pie or donut slices isDonut, explodedIndex
ScatterChart XY scatter plot
RadarChart Spider / radar chart Label per point
GaugeChart Single-value gauge First point y = value
SparklineChart Compact line (no axes chrome)
StackedAreaChart Stacked filled areas Multiple series
WaterfallChart Running totals / P&L steps kWaterfallTypeKey metadata
FunnelChart Conversion funnel Decreasing y values
BubbleChart Sized bubbles in XY space toBubblePoints() extension
HeatmapChart Grid heatmap
CandlestickChart OHLC-style financial bars
TimelineChart Event timeline

Data model

ChartPoint

A single (x, y) value with optional label and metadata (used for waterfall types, bubble size, etc.).

const ChartPoint(x: 0, y: 72, label: 'CPU');

ChartSeries

Named list of points with optional SeriesStyle (color, stroke, markers, gradient).

ChartSeries(
  id: 'sales',
  name: 'Sales',
  points: [20, 25, 30, 28, 35].toChartPoints(),
  style: const SeriesStyle(showMarkers: true),
);

ChartConfig

Global settings shared by all chart widgets:

Property Purpose
series One or more ChartSeries
title / subtitle Header text (dashboard template)
xAxisTitle / yAxisTitle Axis labels
theme Override ChartTheme
template dashboard or plain
showGrid / showAxis Cartesian chrome
showLegend / legendPosition Legend placement
animate / animationDuration Entry animation
curveTension Smooth line curvature (0–1)
viewport Zoom/pan bounds (ChartViewport)
semanticLabel Accessibility label

Convenience extensions

// Iterable<num> → List<ChartPoint>
[20, 25, 30].toChartPoints();

// List<ChartPoint> → ChartSeries
points.toSeries(id: 'a', name: 'Product A');

// (x, y, size) tuples → bubble points
[(10, 20, 40), (25, 35, 80)].toBubblePoints();

Waterfall metadata

Use kWaterfallTypeKey in point metadata for special bars:

ChartPoint(
  x: 0,
  y: 100,
  label: 'Start',
  metadata: {kWaterfallTypeKey: 'absolute'},
),
ChartPoint(
  x: 3,
  y: 0,
  label: 'Subtotal',
  metadata: {kWaterfallTypeKey: 'subtotal'},
),

Supported values: delta (default), absolute, subtotal, total.

Theming

ChartConfig(
  theme: ChartTheme.dark(),
  // or ChartTheme.light(), ChartTheme.dashboard()
  series: [...],
);

ChartTheme controls background, grid, axis, tooltip, crosshair, selection highlight, series palette, shadows, and typography. Per-series colors can override the palette via SeriesStyle.color.

Interactions

ChartWidget (used internally by every chart) supports:

  • Tooltip — hover/tap hit testing (enableTooltip, default true)
  • Crosshair — follows pointer on cartesian charts (enableCrosshair)
  • Zoom & pan — pinch/drag on cartesian charts (enableZoomPan)
  • SelectiononSelection: (ChartHitResult hit) { ... }

Pie, gauge, heatmap, and similar charts disable zoom/crosshair where it does not apply.

Export (PNG / PDF)

Attach a ChartWidgetController and optionally wrap with ChartCard for toolbar buttons:

final controller = ChartWidgetController();

ChartCard(
  config: config,
  controller: controller,
  child: LineChart(config: config, controller: controller),
);

// Programmatic export
final pngBytes = await controller.exportPng();
final pdfBytes = await controller.exportPdfFromConfig(config);

Low-level API without a controller:

final bytes = await ChartExport.toPng(globalKey);

Charts render inside a RepaintBoundary; exports capture the canvas (tooltips overlay is excluded).

Custom charts

Build on the engine layer exported from save_points_charts.dart:

  1. Implement ChartRenderer with a draw(Canvas, Size, ChartContext) method.
  2. Pass your renderer to ChartWidget(config: ..., renderers: [MyRenderer()]).
  3. Optionally register plugins via PluginRegistry and compose layers (GridLayer, AxisLayer, SeriesLayer, …).

Architecture

ChartWidget
  └── ChartEngine (config + theme + renderers)
        └── RenderPipeline / LayerStack
              └── ChartPainter (CustomPaint)

Models live under lib/models/, canvas renderers under lib/charts/, and shared infrastructure (axis, gestures, tooltips, zoom) under lib/core/.

Example app

cd example
flutter run

The demo includes a dashboard layout and an “All charts” gallery with export buttons.

License

Apache License 2.0 — see LICENSE.

Libraries

charts/area_chart/area_chart_renderer
charts/bar_chart/bar_chart_renderer
charts/bubble_chart/bubble_chart_renderer
charts/candlestick_chart/candlestick_chart_renderer
charts/funnel_chart/funnel_chart_renderer
charts/gauge_chart/gauge_chart_renderer
charts/heatmap_chart/heatmap_chart_renderer
charts/line_chart/line_chart_renderer
charts/pie_chart/pie_chart_renderer
charts/radar_chart/radar_chart_renderer
charts/scatter_chart/scatter_chart_renderer
charts/sparkline_chart/sparkline_chart_renderer
charts/stacked_area_chart/stacked_area_chart_renderer
charts/timeline_chart/timeline_chart_renderer
charts/waterfall_chart/waterfall_chart_renderer
core/animations/chart_animation_controller
core/animations/interpolation
core/axis/axis_engine
core/canvas/chart_exporter
core/chrome/chart_chrome
core/coordinates/chart_bounds
core/coordinates/coordinate_transformer
core/engine/chart_context
core/engine/chart_engine
core/engine/chart_renderer
core/engine/plugin_registry
core/engine/render_pipeline
core/gestures/gesture_engine
core/interactions/hit_test_engine
core/interactions/hit_test_result
core/layers/axis_layer
core/layers/background_layer
core/layers/chart_layer
core/layers/chrome_layer
core/layers/grid_layer
core/layers/interaction_layer
core/layers/layer_stack
core/layers/overlay_layer
core/layers/series_layer
core/painters/chart_painter
core/scaling/zoom_pan_controller
core/theme/chart_template
core/theme/chart_theme
core/tooltip/tooltip_controller
core/tooltip/tooltip_data
core/tooltip/tooltip_overlay
core/utils/bezier
core/utils/paint_cache
core/utils/rounded_bar
extensions/chart_extensions
models/chart_config
models/chart_data
models/chart_point
models/chart_series
models/chart_template_style
models/legend_position
models/viewport
save_points_charts
widgets/area_chart
widgets/bar_chart
widgets/bubble_chart
widgets/candlestick_chart
widgets/chart_card
widgets/chart_widget
widgets/chart_widget_controller
widgets/funnel_chart
widgets/gauge_chart
widgets/heatmap_chart
widgets/line_chart
widgets/pie_chart
widgets/radar_chart
widgets/scatter_chart
widgets/sparkline_chart
widgets/stacked_area_chart
widgets/timeline_chart
widgets/waterfall_chart