Created
April 20, 2023 20:28
-
-
Save dsrenesanse/15d8f6166c665d19c754b4adb626e95c to your computer and use it in GitHub Desktop.
Graphica
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
class GraphData { | |
final Color color; | |
final List<int> values; | |
GraphData({ | |
required this.color, | |
required this.values, | |
}); | |
} | |
class Graphica extends CustomPainter { | |
final List<GraphData> graphs; | |
final int indicatorsPadding; | |
final List<String>? dxIndicators; | |
final List<String>? dyIndicators; | |
final Color? dxIndicatorsColor; | |
final Color? dyIndicatorsColor; | |
final Color backgroundColor; | |
final Color dxLineColor; | |
final Color dyLineColor; | |
final double lineWidth; | |
final double graphsWidth; | |
final int xCap; | |
final int yCap; | |
final List<TextPainter> _dxTextPainters = []; | |
final List<TextPainter> _dyTextPainters = []; | |
Graphica({ | |
this.backgroundColor = Colors.white, | |
this.dxLineColor = Colors.black, | |
this.dyLineColor = Colors.black, | |
this.lineWidth = 1.0, | |
required this.graphs, | |
this.indicatorsPadding = 8, | |
this.dxIndicators, | |
List<String>? dyIndicators, | |
this.dyIndicatorsColor, | |
this.dxIndicatorsColor, | |
this.graphsWidth = 2, | |
}) : xCap = | |
graphs.map((g) => g.values.length).reduce((a, b) => a > b ? a : b), | |
yCap = graphs | |
.map((g) => g.values.reduce((a, b) => a > b ? a : b)) | |
.reduce((a, b) => a > b ? a : b), | |
dyIndicators = dyIndicators?.reversed.toList() { | |
_initTextPainters(); | |
} | |
@override | |
void paint(Canvas canvas, Size size) { | |
final h = size.height; | |
final w = size.width; | |
_paintBackground(canvas, h, w); | |
final xCap = | |
graphs.map((g) => g.values.length).reduce((a, b) => a > b ? a : b); | |
final yCap = graphs | |
.map((g) => g.values.reduce((a, b) => a > b ? a : b)) | |
.reduce((a, b) => a > b ? a : b); | |
final dxStep = w / (xCap - 1); | |
final dyStep = h / yCap; | |
if (dxIndicators != null) { | |
_paintXIndicators(canvas, dxStep, h); | |
} | |
if (dyIndicators != null) { | |
_paintYIndicators(canvas, dyStep); | |
} | |
_paintXLines(canvas, dxStep, h); | |
_paintYLines(canvas, dyStep, w, h); | |
for (final g in graphs) { | |
final values = g.values; | |
for (int index = 0; index < values.length - 1; index++) { | |
canvas.drawLine( | |
Offset(dxStep * index, h - (h / yCap * values[index])), | |
Offset(dxStep * (index + 1), h - (h / yCap * values[index + 1])), | |
Paint() | |
..color = g.color | |
..strokeWidth = graphsWidth, | |
); | |
} | |
} | |
} | |
void _initTextPainters() { | |
if (dxIndicators != null) { | |
for (final indicator in dxIndicators!) { | |
_dxTextPainters.add( | |
TextPainter( | |
text: TextSpan( | |
text: indicator, style: TextStyle(color: dxIndicatorsColor)), | |
textDirection: TextDirection.ltr, | |
)..layout(), | |
); | |
} | |
} | |
if (dyIndicators != null) { | |
for (final indicator in dyIndicators!) { | |
_dyTextPainters.add( | |
TextPainter( | |
text: TextSpan( | |
text: indicator, style: TextStyle(color: dyIndicatorsColor)), | |
textDirection: TextDirection.ltr, | |
)..layout(), | |
); | |
} | |
} | |
} | |
void _paintBackground(Canvas canvas, double h, double w) { | |
canvas.drawRect( | |
Rect.fromPoints(Offset.zero, Offset(w, h)), | |
Paint() | |
..style = PaintingStyle.fill | |
..color = backgroundColor, | |
); | |
} | |
void _paintXLines(Canvas canvas, double dxStep, double h) { | |
for (var x = 0; x < xCap; x++) { | |
canvas.drawLine( | |
Offset(dxStep * x, 0), | |
Offset(dxStep * x, h), | |
Paint() | |
..color = dxLineColor | |
..strokeWidth = lineWidth, | |
); | |
} | |
} | |
void _paintYLines(Canvas canvas, double dyStep, double w, double h) { | |
for (var y = 0; y < yCap; y++) { | |
canvas.drawLine( | |
Offset(0, h - dyStep * y), | |
Offset(w, h - dyStep * y), | |
Paint() | |
..color = dyLineColor | |
..strokeWidth = lineWidth, | |
); | |
} | |
} | |
void _paintXIndicators(Canvas canvas, double dxStep, double h) { | |
for (var x = 0; x < xCap; x++) { | |
_dxTextPainters[x].paint( | |
canvas, | |
Offset(x * dxStep, h + indicatorsPadding), | |
); | |
} | |
} | |
void _paintYIndicators(Canvas canvas, double dyStep) { | |
for (var y = 0; y < yCap + 1; y++) { | |
_dyTextPainters[y].paint( | |
canvas, | |
Offset(-_dyTextPainters[y].width - indicatorsPadding, y * dyStep), | |
); | |
} | |
} | |
@override | |
bool shouldRepaint(covariant Graphica oldDelegate) { | |
return oldDelegate.graphs != graphs || | |
oldDelegate.dxIndicators != dxIndicators || | |
oldDelegate.dyIndicators != dyIndicators || | |
oldDelegate.dxIndicatorsColor != dxIndicatorsColor || | |
oldDelegate.dyIndicatorsColor != dyIndicatorsColor || | |
oldDelegate.backgroundColor != backgroundColor || | |
oldDelegate.dxLineColor != dxLineColor || | |
oldDelegate.dyLineColor != dyLineColor || | |
oldDelegate.lineWidth != lineWidth || | |
oldDelegate.graphsWidth != graphsWidth; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment