Skip to content

Commit 5c1f054

Browse files
authored
feat: add gradient support for BarChartRodStackItem (#1979)
1 parent 06835da commit 5c1f054

File tree

5 files changed

+104
-15
lines changed

5 files changed

+104
-15
lines changed

example/lib/presentation/samples/bar/bar_chart_sample5.dart

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,16 @@ class BarChartSample5State extends State<BarChartSample5> {
169169
BarChartRodStackItem(
170170
0,
171171
value1,
172-
AppColors.contentColorGreen,
172+
null,
173+
gradient: LinearGradient(colors: [
174+
AppColors.contentColorWhite.withValues(alpha: 0.8),
175+
AppColors.contentColorGreen.withValues(alpha: 0.5),
176+
AppColors.contentColorCyan.withValues(alpha: 0.2),
177+
], stops: const [
178+
0.1,
179+
0.4,
180+
0.9
181+
], begin: Alignment.topLeft, end: Alignment.bottomRight),
173182
label: isTouched ? 'A' : null,
174183
borderSide: BorderSide(
175184
color: Colors.white,
@@ -189,7 +198,17 @@ class BarChartSample5State extends State<BarChartSample5> {
189198
BarChartRodStackItem(
190199
value1 + value2,
191200
value1 + value2 + value3,
192-
AppColors.contentColorPink,
201+
null,
202+
gradient: LinearGradient(
203+
colors: [
204+
AppColors.contentColorPurple,
205+
AppColors.contentColorRed.withValues(alpha: 0.9),
206+
AppColors.contentColorOrange.withValues(alpha: 0.8),
207+
],
208+
stops: const [0, 0.5, 1],
209+
begin: Alignment.topLeft,
210+
end: Alignment.bottomRight,
211+
),
193212
label: isTouched ? 'C' : null,
194213
borderSide: BorderSide(
195214
color: Colors.white,
@@ -225,8 +244,19 @@ class BarChartSample5State extends State<BarChartSample5> {
225244
BarChartRodStackItem(
226245
0,
227246
-value1,
228-
AppColors.contentColorGreen.withValues(
229-
alpha: isTouched ? shadowOpacity * 2 : shadowOpacity),
247+
null,
248+
gradient: LinearGradient(colors: [
249+
AppColors.contentColorWhite.withValues(
250+
alpha: isTouched ? shadowOpacity * 2 : shadowOpacity),
251+
AppColors.contentColorGreen.withValues(
252+
alpha: isTouched ? shadowOpacity * 2 : shadowOpacity),
253+
AppColors.contentColorCyan.withValues(
254+
alpha: isTouched ? shadowOpacity * 2 : shadowOpacity),
255+
], stops: const [
256+
0.1,
257+
0.4,
258+
0.9
259+
], begin: Alignment.topLeft, end: Alignment.bottomRight),
230260
label: isTouched ? 'A' : null,
231261
borderSide: const BorderSide(color: Colors.transparent),
232262
),
@@ -241,8 +271,24 @@ class BarChartSample5State extends State<BarChartSample5> {
241271
BarChartRodStackItem(
242272
-(value1 + value2),
243273
-(value1 + value2 + value3),
244-
AppColors.contentColorPink.withValues(
245-
alpha: isTouched ? shadowOpacity * 2 : shadowOpacity),
274+
null,
275+
gradient: LinearGradient(
276+
colors: [
277+
AppColors.contentColorPurple.withValues(
278+
alpha: isTouched ? shadowOpacity * 2 : shadowOpacity),
279+
AppColors.contentColorRed.withValues(
280+
alpha: isTouched
281+
? (shadowOpacity * 2) - 0.1
282+
: shadowOpacity),
283+
AppColors.contentColorOrange.withValues(
284+
alpha: isTouched
285+
? (shadowOpacity * 2) - 0.2
286+
: shadowOpacity),
287+
],
288+
stops: const [0, 0.5, 1],
289+
begin: Alignment.topLeft,
290+
end: Alignment.bottomRight,
291+
),
246292
label: isTouched ? 'C' : null,
247293
borderSide: const BorderSide(color: Colors.transparent),
248294
),

lib/src/chart/bar_chart/bar_chart_data.dart

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ class BarChartRodData with EquatableMixin {
471471
/// Each [BarChartRodData] can have a list of [BarChartRodStackItem] (with different colors
472472
/// and position) to represent a Stacked Chart rod,
473473
class BarChartRodStackItem with EquatableMixin {
474-
/// Renders a section of Stacked Chart from [fromY] to [toY] with [color]
474+
/// Renders a section of Stacked Chart from [fromY] to [toY] with [color] or [gradient]
475475
/// for example if you want to have a Stacked Chart with three colors:
476476
/// ```dart
477477
/// BarChartRodData(
@@ -484,14 +484,19 @@ class BarChartRodStackItem with EquatableMixin {
484484
/// ]
485485
/// )
486486
/// ```
487+
/// To use the [gradient], set [color] to null
487488
BarChartRodStackItem(
488489
this.fromY,
489490
this.toY,
490491
this.color, {
492+
this.gradient,
491493
this.label,
492494
this.labelStyle,
493495
this.borderSide = Utils.defaultBorderSide,
494-
});
496+
}) : assert(
497+
color != null || gradient != null,
498+
'You must provide either a color or gradient',
499+
);
495500
final String? label;
496501
final TextStyle? labelStyle;
497502

@@ -502,7 +507,10 @@ class BarChartRodStackItem with EquatableMixin {
502507
final double toY;
503508

504509
/// Renders a Stacked Chart section with [color]
505-
final Color color;
510+
final Color? color;
511+
512+
/// Renders a Stacked Chart section with [gradient]
513+
final Gradient? gradient;
506514

507515
/// Renders border stroke for a Stacked Chart section
508516
final BorderSide borderSide;
@@ -513,6 +521,7 @@ class BarChartRodStackItem with EquatableMixin {
513521
double? fromY,
514522
double? toY,
515523
Color? color,
524+
Gradient? gradient,
516525
String? label,
517526
TextStyle? labelStyle,
518527
BorderSide? borderSide,
@@ -521,6 +530,7 @@ class BarChartRodStackItem with EquatableMixin {
521530
fromY ?? this.fromY,
522531
toY ?? this.toY,
523532
color ?? this.color,
533+
gradient: gradient ?? this.gradient,
524534
label: label ?? this.label,
525535
labelStyle: labelStyle ?? this.labelStyle,
526536
borderSide: borderSide ?? this.borderSide,
@@ -535,15 +545,17 @@ class BarChartRodStackItem with EquatableMixin {
535545
BarChartRodStackItem(
536546
lerpDouble(a.fromY, b.fromY, t)!,
537547
lerpDouble(a.toY, b.toY, t)!,
538-
Color.lerp(a.color, b.color, t)!,
548+
Color.lerp(a.color, b.color, t),
549+
gradient: Gradient.lerp(a.gradient, b.gradient, t),
539550
label: b.label,
540551
labelStyle: b.labelStyle,
541552
borderSide: BorderSide.lerp(a.borderSide, b.borderSide, t),
542553
);
543554

544555
/// Used for equality check, see [EquatableMixin].
545556
@override
546-
List<Object?> get props => [fromY, toY, color, label, labelStyle, borderSide];
557+
List<Object?> get props =>
558+
[fromY, toY, color, gradient, label, labelStyle, borderSide];
547559
}
548560

549561
/// Holds values to draw a rod in rear of the main rod.

lib/src/chart/bar_chart/bar_chart_painter.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,14 @@ class BarChartPainter extends AxisChartPainter<BarChartData> {
311311
final stackToY = getPixelY(stackItem.toY, viewSize, holder);
312312

313313
final isNegative = stackItem.toY < stackItem.fromY;
314-
_barPaint.color = stackItem.color;
315314
final rect = isNegative
316315
? Rect.fromLTRB(left, stackFromY, right, stackToY)
317316
: Rect.fromLTRB(left, stackToY, right, stackFromY);
317+
_barPaint.setColorOrGradient(
318+
stackItem.color,
319+
stackItem.gradient,
320+
rect,
321+
);
318322
canvasWrapper
319323
..save()
320324
..clipRect(rect)

repo_files/documentations/bar_chart.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ enum values {`start`, `end`, `center`, `spaceEvenly`, `spaceAround`, `spaceBetwe
7777
|fromY|draw stack item from this value|null|
7878
|toY|draw stack item to this value|null|
7979
|color|color of the stack item|null|
80+
|gradient|gradient of the stack item|null|
8081
|label|optional text label for the stack item|null|
8182
|labelStyle|optional TextStyle for the label|null|
8283
|borderSide|draw border stroke for each stack item|null|

test/chart/bar_chart/bar_chart_painter_test.dart

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:ui' as ui show Gradient;
2+
13
import 'package:fl_chart/fl_chart.dart';
24
import 'package:fl_chart/src/chart/bar_chart/bar_chart_helper.dart';
35
import 'package:fl_chart/src/chart/bar_chart/bar_chart_painter.dart';
@@ -1277,7 +1279,10 @@ void main() {
12771279
BarChartRodStackItem(
12781280
5,
12791281
10,
1280-
const Color(0x44444444),
1282+
null,
1283+
gradient: const LinearGradient(
1284+
colors: [Color(0xFFFF0000), Color(0xFF00FF00)],
1285+
),
12811286
label: '5',
12821287
),
12831288
],
@@ -1286,7 +1291,13 @@ void main() {
12861291
),
12871292
];
12881293

1289-
final data = BarChartData(barGroups: barGroups);
1294+
final (minY, maxY) = BarChartHelper().calculateMaxAxisValues(barGroups);
1295+
1296+
final data = BarChartData(
1297+
barGroups: barGroups,
1298+
minY: minY,
1299+
maxY: maxY,
1300+
);
12901301

12911302
final barChartPainter = BarChartPainter();
12921303
final holder =
@@ -1309,6 +1320,7 @@ void main() {
13091320
final paint = inv.positionalArguments[1] as Paint;
13101321
results.add({
13111322
'paint_color': paint.color,
1323+
'gradient': paint.shader is ui.Gradient,
13121324
});
13131325
});
13141326

@@ -1326,9 +1338,17 @@ void main() {
13261338
results[3]['paint_color'],
13271339
isSameColorAs(const Color(0x33333333)),
13281340
);
1341+
expect(
1342+
results[3]['gradient'],
1343+
false,
1344+
);
13291345
expect(
13301346
results[4]['paint_color'],
1331-
isSameColorAs(const Color(0x44444444)),
1347+
isSameColorAs(const Color(0xFF000000)),
1348+
);
1349+
expect(
1350+
results[4]['gradient'],
1351+
true,
13321352
);
13331353
});
13341354

@@ -3418,4 +3438,10 @@ void main() {
34183438
).called(2);
34193439
});
34203440
});
3441+
3442+
group('BarChartRodStackItem()', () {
3443+
test('throws an exception if color and gradient is null', () {
3444+
expect(() => BarChartRodStackItem(0, 10, null), throwsAssertionError);
3445+
});
3446+
});
34213447
}

0 commit comments

Comments
 (0)