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).
Contents
- What's new
- Features
- Installation
- Quick start
- Chart types
- Render styles
- Smooth curves
- Data model
- Convenience extensions
- Waterfall metadata
- Theming
- Interactions
- Custom charts
- Architecture
- Example app
- Links
What's new
- π¨ Render styles β pick
gradient,flat, orglassper chart viaChartConfig.style. See Render styles. - β¨ Modern visuals by default β gradient fills, soft glow, and radial highlights across every chart type.
- π Overshoot-free smooth curves β monotone cubic interpolation keeps smoothed lines and stacked areas faithful to the data. See Smooth curves.
- π Refreshed dark theme β deep-navy gradient background, plus
ChartTheme.backgroundGradientfor custom gradient backdrops. - π§ Upgraded example app β navigation drawer, light/dark toggle, and a live render-style picker.
Note: the PNG/PDF export API (
ChartExport,ChartCard,ChartWidgetController) was removed in 2.0.0, dropping the
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, β¦) - Render styles β¨ β switch any chart between
ChartStyle.gradient(default),flat, orglasswith one field - Modern visuals β gradient fills, soft glow, and radial highlights out of the box
- Overshoot-free curves β smooth lines use monotone cubic interpolation (no false peaks or dips between points)
- Interactions β tooltips, crosshair, tap selection, pinch zoom & pan (where applicable)
- Theming β
ChartTheme.light(),ChartTheme.dark()(deep-navy gradient background),ChartTheme.dashboard(), or fully custom colors and gradients - Templates β
ChartTemplateStyle.dashboard(title, legend, grid) orplain(minimal chrome) - Animations β configurable duration and curve tension for smooth line/area transitions
- Accessibility β
semanticLabelonChartConfigfor screen readers - Extensible engine β layer stack, render pipeline, and
ChartRendererplugins for custom charts - Zero dependencies β pure-Flutter canvas rendering, no third-party runtime packages
Requirements
| Version | |
|---|---|
| Dart SDK | ^3.12.0 |
| Flutter | >=1.17.0 |
Installation
Add to pubspec.yaml:
dependencies:
save_points_chart: ^1.9.2
Or from the command line:
flutter pub add save_points_chart
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),
);
}
}
The same ChartConfig drops into any chart widget β swap LineChart for BarChart, AreaChart, ScatterChart, and so on without touching your data.
Chart types
| Widget | Description | Notable options |
|---|---|---|
LineChart |
Cartesian line series | mode: LineChartMode.smooth (default) / straight, fillArea |
BarChart |
Vertical or horizontal bars | orientation: BarChartOrientation, layout: BarChartLayout.grouped (default) / 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 | β |
Every widget accepts an optional theme override that takes precedence over the one on ChartConfig.
Render styles
Set style on ChartConfig to change how series are painted β independent of the color theme. Every chart type honors it.
ChartConfig(
style: ChartStyle.glass, // gradient (default) Β· flat Β· glass
series: [...],
);
// or derive a variant
config.copyWith(style: ChartStyle.flat);
| Style | Look |
|---|---|
ChartStyle.gradient (default) |
Gradient fills & strokes, soft glow, radial highlights β vibrant and dimensional |
ChartStyle.flat |
Solid fills, crisp strokes, no gradients or glow β calm and data-first |
ChartStyle.glass |
Frosted translucent fills with a light highlight β glassmorphism |
Smooth curves
Smooth lines (LineChart, AreaChart, SparklineChart, StackedAreaChart) use monotone cubic interpolation (FritschβCarlson) rather than a plain cardinal spline. The curve never overshoots the data β no false peaks, no dips below a baseline, no excursions below zero β so a smoothed line stays a faithful reading of the values while still looking smooth.
LineChart(
config: config,
mode: LineChartMode.smooth, // default; use .straight for polyline
);
curveTension (on ChartConfig) applies to the cardinal fallback used for non-monotonic x data.
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:
ChartSeries(
id: 'sales',
name: 'Sales',
points: [20, 25, 30, 28, 35].toChartPoints(),
style: const SeriesStyle(showMarkers: true),
);
SeriesStyle fields:
| Field | Default | Purpose |
|---|---|---|
color |
theme palette | Stroke / fill base color |
strokeWidth |
2.0 |
Line thickness |
fillColor |
β | Area fill override |
gradient |
β | Gradient fill (overrides fillColor) |
showMarkers |
false |
Draw point markers |
markerRadius |
4.0 |
Marker size |
opacity |
1.0 |
Series opacity |
ChartConfig
Global settings shared by all chart widgets:
| Property | Default | Purpose |
|---|---|---|
series |
[] |
One or more ChartSeries |
title / subtitle |
β | Header text (dashboard template) |
xAxisTitle / yAxisTitle |
β | Axis labels |
theme |
β | Override ChartTheme |
template |
dashboard |
dashboard or plain |
style |
gradient |
Render style β gradient / flat / glass |
showGrid / showAxis |
true |
Cartesian chrome |
showBorder |
false |
Outer chart border |
showLegend / legendPosition |
false / bottom |
Legend toggle and placement |
barBorderRadius |
4 |
Bar corner radius |
animate / animationDuration |
true / 300ms |
Entry animation |
curveTension |
0.35 |
Smooth line curvature (0β1) |
viewport |
auto | Zoom/pan bounds (ChartViewport) |
semanticLabel |
β | Accessibility label |
ChartConfig is immutable β use copyWith(...) to derive variants.
ChartViewport
Constrains the visible data-space region. Build one from your data with ChartViewport.fromPoints(xs, ys, padding: 0.05), or set bounds explicitly:
const ChartViewport(minX: 0, maxX: 12, minY: 0, maxY: 300);
Convenience extensions
// Iterable<num> β List<ChartPoint> (x auto-indexed; tune with startX / step)
[20, 25, 30].toChartPoints();
[20, 25, 30].toChartPoints(startX: 2020, step: 1);
// 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. A theme set on a widget takes precedence over the one on ChartConfig.
Themes can paint a gradient background via the optional backgroundGradient field (the dark preset ships with a deep-navy gradient):
const ChartTheme(
backgroundColor: Color(0xFF121826), // fallback when gradient is null
backgroundGradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xFF1B2438), Color(0xFF0D1220)],
),
// β¦remaining theme fields
);
Interactions
ChartWidget (used internally by every chart) supports:
- Tooltip β hover/tap hit testing (
enableTooltip, defaulttrue) - Crosshair β follows pointer on cartesian charts (
enableCrosshair, defaulttrue) - Zoom & pan β pinch/drag on cartesian charts (
enableZoomPan, defaulttrue) - Selection β
onSelection: (ChartHitResult hit) { ... }
Pie, gauge, heatmap, and similar charts disable zoom/crosshair where it does not apply.
Custom charts
Build on the engine layer exported from save_points_charts.dart:
- Implement
ChartRendererwith adraw(Canvas, Size, ChartContext)method. - Pass your renderer to
ChartWidget(config: ..., renderers: [MyRenderer()]). - Optionally register plugins via
PluginRegistryand 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 a navigation drawer, a light/dark toggle, and a render-style picker (gradient / flat / glass) in the app bar.
Links
Contributing
Issues and pull requests are welcome on the GitHub repository. Please run flutter analyze and flutter test before submitting.
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/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
- core/utils/series_paint
- extensions/chart_extensions
- models/chart_config
- models/chart_data
- models/chart_point
- models/chart_series
- models/chart_style
- 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_widget
- 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