I want to make a chart with a gradient under the highest value, exactly like this :
how can I do that?
You should use CustomPaint
.
class CurvedChartPainter extends CustomPainter {
final List<double> xValues;
final List<double> yValues;
final Color color;
final double strokeWidth;
CurvedChartPainter({
@required this.xValues,
@required this.yValues,
@required this.strokeWidth,
this.color,
});
@override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = color ?? Color(0xFFF63E02);
paint.style = PaintingStyle.stroke;
paint.strokeWidth = strokeWidth;
var path = Path();
if (xValues.length > 1 && yValues.isNotEmpty) {
final maxValue = yValues.last;
final firstValueHeight = size.height * (xValues.first / maxValue);
path.moveTo(0.0, size.height - firstValueHeight);
final itemXDistance = size.width / (xValues.length - 1);
for (var i = 1; i < xValues.length; i++) {
final x = itemXDistance * i;
final valueHeight = size.height -
strokeWidth -
((size.height - strokeWidth) * (xValues[i].value / maxValue));
final previousValueHeight = size.height -
strokeWidth -
((size.height - strokeWidth) *
(xValues[i - 1].value / maxValue));
path.quadraticBezierTo(
x - (itemXDistance / 2) - (itemXDistance / 8),
previousValueHeight,
x - (itemXDistance / 2),
valueHeight + ((previousValueHeight - valueHeight) / 2),
);
path.quadraticBezierTo(
x - (itemXDistance / 2) + (itemXDistance / 8),
valueHeight,
x,
valueHeight,
);
}
}
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => oldDelegate != this;
}
class MyCurvedChart extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFF63E02).withOpacity(0.45),
Colors.white.withOpacity(0.0),
],
),
),
width: 200,
height: 150,
child: CustomPaint(
painter: CurvedChartPainter(
xValues: [
0.0,
1.0,
0.0,
2.0,
3.0,
1.0,
1.5,
],
yValues: [
0.0,
1.0,
2.0,
3.0,
4.0,
],
strokeWidth: 3.0,
),
),
);
}
}
now our output would look like something like this:
CostumClipper
that clips the Container
exactly like the chart:class CurvedChartClipper extends CustomClipper<Path> {
final List<double> xValues;
final List<double> yValues;
final double strokeWidth;
CurvedChartClipper({
@required this.xValues,
@required this.yValues,
@required this.strokeWidth,
});
@override
Path getClip(Size size) {
var path = Path();
if (xValues.length > 1 && yValues.isNotEmpty) {
final maxValue = yValues.last;
final firstValueHeight = size.height * (xValues.first / maxValue);
path.moveTo(0.0, size.height - firstValueHeight);
final itemXDistance = size.width / (xValues.length - 1);
for (var i = 1; i < xValues.length; i++) {
final x = itemXDistance * i;
final valueHeight = size.height -
strokeWidth -
((size.height - strokeWidth) * (xValues[i].value / maxValue));
final previousValueHeight = size.height -
strokeWidth -
((size.height - strokeWidth) *
(xValues[i - 1].value / maxValue));
path.quadraticBezierTo(
x - (itemXDistance / 2) - (itemXDistance / 8),
previousValueHeight,
x - (itemXDistance / 2),
valueHeight + ((previousValueHeight - valueHeight) / 2),
);
path.quadraticBezierTo(
x - (itemXDistance / 2) + (itemXDistance / 8),
valueHeight,
x,
valueHeight,
);
}
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
path.lineTo(0, 0);
}
return path;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) =>
oldClipper != this;
}
ClipPath
widget to clip the Container
that has the gradient:class MyCurvedChart extends StatelessWidget {
@override
Widget build(BuildContext context) {
final xValues = [
0.0,
1.0,
0.0,
2.0,
3.0,
1.0,
1.5,
];
final yValues = [
0.0,
1.0,
2.0,
3.0,
4.0,
];
final stroke = 3.0;
return ClipPath(
clipper: CurvedChartClipper(
xValues: xValues,
yValues: yValues,
strokeWidth: stroke,
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFF63E02).withOpacity(0.45),
Colors.white.withOpacity(0.0),
],
),
),
width: 200,
height: 150,
child: CustomPaint(
painter: CurvedChartPainter(
xValues: xValues,
yValues: yValues,
strokeWidth: stroke,
),
),
),
);
}
}