Skip to content

Commit a9147f0

Browse files
authored
feat: Add the gauge marker painter (#2096)
1 parent d7bf644 commit a9147f0

7 files changed

Lines changed: 1145 additions & 126 deletions

File tree

Lines changed: 41 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import 'dart:math';
2-
import 'dart:ui';
3-
41
import 'package:fl_chart/fl_chart.dart';
52
import 'package:fl_chart_app/presentation/resources/app_resources.dart';
63
import 'package:flutter/material.dart';
@@ -15,6 +12,12 @@ class GaugeChartSample1 extends StatefulWidget {
1512
class GaugeChartSample1State extends State<GaugeChartSample1> {
1613
double _value = 0.5;
1714

15+
// Continuous min/max thresholds — deliberately off the 11-tick grid
16+
// (0.0, 0.1, ..., 1.0) to show GaugeMarker carries an arbitrary
17+
// value, not a discrete tick index.
18+
static const _minValue = 0.23;
19+
static const _maxValue = 0.77;
20+
1821
@override
1922
Widget build(BuildContext context) {
2023
return Padding(
@@ -40,16 +43,46 @@ class GaugeChartSample1State extends State<GaugeChartSample1> {
4043
position: GaugeTickPosition.center,
4144
count: 11,
4245
offset: 0,
43-
painter: _MyCustomGaugeMinMaxTickPainter(
46+
painter: GaugeTickCirclePainter(
4447
color: AppColors.contentColorWhite,
4548
radius: 5,
46-
minIndex: 2,
47-
maxIndex: 8,
48-
minMaxLineLength: 40,
49-
minMaxLineStrokeWidth: 4,
5049
),
5150
checkToShowTick: GaugeTicks.hideEndpoints,
5251
),
52+
markers: const [
53+
GaugeMarker(
54+
value: _minValue,
55+
position: GaugeTickPosition.center,
56+
painter: GaugeMarkerLinePainter(
57+
length: 40,
58+
thickness: 4,
59+
color: Colors.green,
60+
label: 'Min',
61+
labelStyle: TextStyle(
62+
color: Colors.green,
63+
fontSize: 12,
64+
fontWeight: FontWeight.bold,
65+
),
66+
labelSide: GaugeMarkerLabelSide.inward,
67+
),
68+
),
69+
GaugeMarker(
70+
value: _maxValue,
71+
position: GaugeTickPosition.center,
72+
painter: GaugeMarkerLinePainter(
73+
length: 40,
74+
thickness: 4,
75+
color: Colors.red,
76+
label: 'Max',
77+
labelStyle: TextStyle(
78+
color: Colors.red,
79+
fontSize: 12,
80+
fontWeight: FontWeight.bold,
81+
),
82+
labelSide: GaugeMarkerLabelSide.inward,
83+
),
84+
),
85+
],
5386
pointers: [
5487
// Needle extending from center toward the current value.
5588
GaugePointer(
@@ -95,97 +128,3 @@ class GaugeChartSample1State extends State<GaugeChartSample1> {
95128
);
96129
}
97130
}
98-
99-
class _MyCustomGaugeMinMaxTickPainter extends GaugeTickCirclePainter {
100-
_MyCustomGaugeMinMaxTickPainter({
101-
super.color,
102-
super.radius,
103-
required this.minIndex,
104-
required this.maxIndex,
105-
required this.minMaxLineLength,
106-
required this.minMaxLineStrokeWidth,
107-
this.textOffset = 6,
108-
this.minTextStyle = const TextStyle(
109-
color: Colors.green,
110-
fontSize: 12,
111-
fontWeight: FontWeight.bold,
112-
),
113-
this.maxTextStyle = const TextStyle(
114-
color: Colors.red,
115-
fontSize: 12,
116-
fontWeight: FontWeight.bold,
117-
),
118-
}) : super();
119-
120-
final int minIndex;
121-
final int maxIndex;
122-
final double minMaxLineLength;
123-
final double minMaxLineStrokeWidth;
124-
final double textOffset;
125-
final TextStyle minTextStyle;
126-
final TextStyle maxTextStyle;
127-
128-
final _paint = Paint();
129-
130-
@override
131-
void draw(Canvas canvas, GaugeTickInfo tickInfo) {
132-
super.draw(canvas, tickInfo);
133-
134-
if (tickInfo.index != minIndex && tickInfo.index != maxIndex) {
135-
return;
136-
}
137-
final isMin = tickInfo.index == minIndex;
138-
final text = isMin ? "Min" : "Max";
139-
final textStyle = isMin ? minTextStyle : maxTextStyle;
140-
final rotation = isMin ? pi : 0.0;
141-
final textPainter = TextPainter(
142-
text: TextSpan(text: text, style: textStyle),
143-
textDirection: TextDirection.ltr,
144-
)..layout();
145-
// 180 degrees
146-
canvas.rotate(rotation);
147-
final offsetX = isMin
148-
? 0 + textPainter.width + textOffset
149-
: 0 - textPainter.width - minMaxLineLength / 2 - textOffset;
150-
textPainter.paint(canvas, Offset(offsetX, 0 - textPainter.height / 2));
151-
_paint.color = textStyle.color!;
152-
_paint.strokeWidth = minMaxLineStrokeWidth;
153-
canvas.drawLine(
154-
Offset(0 - minMaxLineLength / 2, 0),
155-
Offset(0 + minMaxLineLength / 2, 0),
156-
_paint,
157-
);
158-
}
159-
160-
@override
161-
GaugeTickPainter lerp(GaugeTickPainter b, double t) {
162-
if (b is! _MyCustomGaugeMinMaxTickPainter) {
163-
return b;
164-
}
165-
return _MyCustomGaugeMinMaxTickPainter(
166-
color: Color.lerp(color, b.color, t)!,
167-
radius: lerpDouble(radius, b.radius, t)!,
168-
minIndex: minIndex,
169-
maxIndex: maxIndex,
170-
minMaxLineLength: lerpDouble(minMaxLineLength, b.minMaxLineLength, t)!,
171-
minMaxLineStrokeWidth:
172-
lerpDouble(minMaxLineStrokeWidth, b.minMaxLineStrokeWidth, t)!,
173-
textOffset: lerpDouble(textOffset, b.textOffset, t)!,
174-
minTextStyle: TextStyle.lerp(minTextStyle, b.minTextStyle, t)!,
175-
maxTextStyle: TextStyle.lerp(maxTextStyle, b.maxTextStyle, t)!,
176-
);
177-
}
178-
179-
@override
180-
List<Object?> get props =>
181-
[
182-
super.props,
183-
minIndex,
184-
maxIndex,
185-
minMaxLineLength,
186-
minMaxLineStrokeWidth,
187-
textOffset,
188-
minTextStyle,
189-
maxTextStyle,
190-
];
191-
}

0 commit comments

Comments
 (0)