draw method
Draws the chart. progress is the entrance reveal in 0..1 (1 = fully drawn).
Implementation
@override
void draw(
Canvas canvas,
Size size,
DrafterThemeColors theme,
double progress,
) {
if (points.length < 2) return;
final values = [for (final p in points) drafterFinite(p.value)];
final scale = _scaleFor(size);
final bounds = scale.bounds;
final maxValue = scale.maxValue;
// Y grid + labels (4 ticks).
const tickCount = 4;
final gridPaint = Paint()
..color = theme.grid
..style = PaintingStyle.stroke
..strokeWidth = 1;
for (var i = 0; i <= tickCount; i++) {
final frac = i / tickCount;
final y = bounds.bottom - frac * bounds.height;
canvas.drawLine(
Offset(bounds.left, y),
Offset(bounds.right, y),
gridPaint,
);
final tickValue = maxValue * frac;
drawChartText(
canvas,
ChartFormatting.format(tickValue),
Offset(bounds.left - 6, y),
color: theme.label,
h: HAlign.end,
v: VAlign.center,
);
}
// Map points into pixel space via the shared scale.
final pixelPoints = <Offset>[
for (var index = 0; index < values.length; index++)
Offset(scale.xForIndex(index), scale.yForValue(values[index])),
];
// Smooth area + line + reveal + end dot (shared helper).
drawSmoothLine(
canvas,
points: pixelPoints,
color: color,
baseline: bounds.bottom,
progress: progress,
strokeWidth: 5,
);
// Vertex dots, revealed alongside the trace.
final revealRight = bounds.left + bounds.width * progress.clamp(0.0, 1.0);
for (final point in pixelPoints) {
if (point.dx <= revealRight + 0.5) {
drawVertexDot(canvas, point, color, 4);
}
}
// X labels, thinned so they stay legible at small sizes (at most ~6). Each
// label travels with its point, so labels can never shift or run short.
const maxLabels = 6;
final labelStride = math.max(
1,
(pixelPoints.length + maxLabels - 1) ~/ maxLabels,
);
for (var index = 0; index < pixelPoints.length; index++) {
if (index % labelStride != 0) continue;
final label = points[index].label;
if (label.isEmpty) continue;
drawChartText(
canvas,
label,
Offset(pixelPoints[index].dx, bounds.bottom + 13),
color: theme.label,
h: HAlign.center,
v: VAlign.center,
);
}
}