paint method
Paint this render object into the given context at the given offset.
Subclasses should override this method to provide a visual appearance for themselves. The render object's local coordinate system is axis-aligned with the coordinate system of the context's canvas and the render object's local origin (i.e, x=0 and y=0) is placed at the given offset in the context's canvas.
Do not call this function directly. If you wish to paint yourself, call
markNeedsPaint instead to schedule a call to this function. If you wish
to paint one of your children, call PaintingContext.paintChild on the
given context.
When painting one of your children (via a paint child function on the given context), the current canvas held by the context might change because draw operations before and after painting children might need to be recorded on separate compositing layers.
Implementation
@override
void paint(PaintingContext context, Offset offset) {
final canvas = context.canvas;
canvas.save();
canvas.translate(offset.dx, offset.dy);
if (_staticPicture == null || _staticSize != size) {
_rebuildStaticPicture(size);
}
canvas.drawPicture(_staticPicture!);
final center = size.center(Offset.zero);
final radius = size.shortestSide / 2 - _effectiveTrackWidth / 2 - 4;
final startRad = degToRad(_startAngleDeg);
final sweepRad = degToRad(_sweepAngleDeg);
final frac = ((_controller.value - _min) / (_max - _min)).clamp(0.0, 1.0);
final valueSweep = frac * sweepRad;
if (valueSweep > 0) {
// Reverse: fill from far end of track backward
final arcStart = _reverse ? startRad + sweepRad - valueSweep : startRad;
final rect = Rect.fromCircle(center: center, radius: radius);
// Glow pass
final glowR = _tokens.valueGlowRadius;
if (glowR > 0) {
final glowColor =
_tokens.valueGlowColor ?? _tokens.valueColor.withValues(alpha: 0.5);
canvas.drawArc(
rect,
arcStart,
valueSweep,
false,
Paint()
..color = glowColor
..style = PaintingStyle.stroke
..strokeWidth = _tokens.valueStrokeWidth
..strokeCap = _tokens.trackStrokeCap
..maskFilter = MaskFilter.blur(BlurStyle.outer, glowR),
);
}
if (_tokens.valueGradient != null) {
canvas.drawArc(
rect,
arcStart,
valueSweep,
false,
Paint()
..shader = _tokens.valueGradient!.createShader(rect)
..style = PaintingStyle.stroke
..strokeWidth = _tokens.valueStrokeWidth
..strokeCap = _tokens.trackStrokeCap,
);
} else {
canvas.drawArc(
rect,
arcStart,
valueSweep,
false,
Paint()
..color = _tokens.valueColor
..style = PaintingStyle.stroke
..strokeWidth = _tokens.valueStrokeWidth
..strokeCap = _tokens.trackStrokeCap,
);
}
// End-cap dot at the value tip
final endAngle = arcStart + valueSweep;
canvas.drawCircle(
Offset(
center.dx + math.cos(endAngle) * radius,
center.dy + math.sin(endAngle) * radius,
),
_tokens.valueStrokeWidth / 2,
Paint()..color = _tokens.valueColor,
);
}
// Centre label via PictureRecorder (CanvasKit text workaround)
if (_showValue) {
final labelText = _centerLabel ?? _fmtWithUnit(_controller.value);
final tp = TextPainter(
text: TextSpan(
text: labelText,
style: _centerLabelStyle ??
_tokens.labelStyle
.copyWith(fontSize: 22, fontWeight: FontWeight.bold),
),
textDirection: TextDirection.ltr,
)..layout();
final rec = ui.PictureRecorder();
tp.paint(Canvas(rec), Offset.zero);
final pic = rec.endRecording();
canvas.save();
canvas.translate(center.dx - tp.width / 2, center.dy - tp.height / 2);
canvas.drawPicture(pic);
canvas.restore();
}
canvas.restore();
}