Canvas tutorial 04 | How to draw a pie chart and with a round angle in the flutter?

This Article is posted by niebin312 at 1/7/2019 5:17:45 PM




When we draw an arc, which is close with a straight line, not with a round angle, so I will tell you how to draw an arc with a round angle.

We often have many to data to show in the flutter, some often choose to show as a pie chart. In this tutorial, I will tell you how to do it. But before it, you should know how to use the canvas, if you do not know you can look https://medium.com/flutteropen/canvas-tutorial-01-how-to-use-the-canvas-in-the-flutter-8aade29ddc9

0. What we will implement?

Before we start our work, let’s see the product as below.

https://cdn-images-1.medium.com/max/1200/1*xB6wcnI5GdKmN-K0U7MohA.png" src="https://cdn-images-1.medium.com/max/1200/1*xB6wcnI5GdKmN-K0U7MohA.png" style="border: 0px; display: block; position: absolute; top: 0px; left: 0px; width: 700px; height: 247px; margin: auto; z-index: 100; visibility: visible; opacity: 1; backface-visibility: hidden; transition: visibility 0s linear 0s, opacity 0.4s ease 0s;">
our products

1. The principle of an arc with a round angle.

In the flutter, we can just draw an arc with right angle directly, but how to create an arc with a round angle? We have an idea show below.

https://cdn-images-1.medium.com/max/1200/1*F1ydicEt2mufIT7cBCJ2pg.png" src="https://cdn-images-1.medium.com/max/1200/1*F1ydicEt2mufIT7cBCJ2pg.png" style="border: 0px; display: block; position: absolute; top: 0px; left: 0px; width: 700px; height: 224px; margin: auto; z-index: 100; visibility: visible; opacity: 1; backface-visibility: hidden; transition: visibility 0s linear 0s, opacity 0.4s ease 0s;">

If we draw an arc, it will be like theorignal picture, sometimes we do not like it, we just want a one with a round angle above, so we can add each circle for both of them. The picture is very clear for you to understand. So when we want to draw an arc with two round angle end. We need to draw a common arc first, then two circles.

2. Draw a common arc.

It is easy, we just use the API in the flutter. We create a function to use, if we input right param, we will get an arc.

void _drawArcWithCenter(
Canvas canvas,
Paint paint, {
Offset center,
double radius,
startRadian = 0.0,
sweepRadian = pi,
}) {
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
startRadian,
sweepRadian,
false,
paint,
);
}

3. Draw our two circles.

We will draw two circles for the arc, but sometimes we do not need the round angle yet. So we need the params to choose whether or not we need them. The code is below, the hasStartArc,hasEndArc params mean that we whether or not need the start circle or the end circle. the other params are same as the arc we draw above.

void _drawArcTwoPoint(Canvas canvas, Paint paint,
{Offset center,
double radius,
startRadian = 0.0,
sweepRadian = pi,
hasStartArc = false,
hasEndArc = false}) {
var smallR = paint.strokeWidth / 2;
paint.strokeWidth = smallR;
if (hasStartArc) {
var startCenter = LineCircle.radianPoint(
Point(center.dx, center.dy), radius, startRadian);
paint.style = PaintingStyle.fill;
canvas.drawCircle(Offset(startCenter.x, startCenter.y), smallR, paint);
}
if (hasEndArc) {
var endCenter = LineCircle.radianPoint(
Point(center.dx, center.dy), radius, startRadian + sweepRadian);
paint.style = PaintingStyle.fill;
canvas.drawCircle(Offset(endCenter.x, endCenter.y), smallR, paint);
}
}

4. Draw a pie chart.

Sometimes, we have some set represent all of our data, we want to show them in one pie chart, so first, we need to calculate the total count of the data. Then calculate the proportion of the radian of the circle, as we know, the radian of the circle is 2*pi, so we can get the radian, in our https://medium.com/flutteropen/canvas-tutorial-03-how-to-draw-a-regular-round-angle-polygon-83b055b7af6c" class="markup--anchor markup--p-anchor" target="_blank" style="color: inherit; -webkit-tap-highlight-color: rgba(0, 0, 0, 0.54); background-repeat: repeat-x; background-image: linear-gradient(to right, currentcolor 100%, currentcolor 0px); background-size: 1px 1px; background-position: 0px calc(1em + 1px);">fore tutorial, we can easy to get the points of the small circles.

Calculate radian with each part.

List<double> radians = List<double>();
for (double d in sources) {
double radian = d * 2 * pi / total;
radians.add(radian);
}

Draw all arc with radians.

for (int i = 0; i < radians.length; i++) {
var rd = radians[i];
paint.color = colors[i % colors.length];
paint.strokeWidth = paintWidth;
_drawArcWithCenter(canvas, paint,
center: center, radius: radius, startRadian: startA, sweepRadian: rd);
startA += rd;
}

Draw all round angle with end circles

for (int i = 0; i < radians.length; i++) {
var rd = radians[i];
paint.color = colors[i % colors.length];
paint.strokeWidth = paintWidth;
_drawArcTwoPoint(canvas, paint,
center: center,
radius: radius,
startRadian: startA,
sweepRadian: rd,
hasEndArc: true);
startA += rd;
}

But sometimes we need to show one part is very special, so I define a current part that can show two round angles in the pie chart. Also, you can use the param of curPaintWidthto make it different from other parts. Let’s see the whole code fragment of drawing piechart.

void _drawArcGroup(Canvas canvas,
{Offset center,
double radius,
List<double> sources,
List<Color> colors,
double startAngle = 0.0,
double paintWidth = 10.0,
bool hasEnd = false,
hasCurrent = false,
int curIndex = 0,
curPaintWidth = 12.0}) {
assert(sources != null && sources.length > 0);
assert(colors != null && colors.length > 0);
var paint = Paint()
..style = PaintingStyle.fill
..color = BLUE_NORMAL
..strokeWidth = paintWidth
..isAntiAlias = true;
double total = 0;
for (double d in sources) {
total += d;
}
assert(total > 0.0);
List<double> radians = List<double>();
for (double d in sources) {
double radian = d * 2 * pi / total;
radians.add(radian);
}
var startA = startAngle;
paint.style = PaintingStyle.stroke;
var curStartAngle = 0.0;
for (int i = 0; i < radians.length; i++) {
var rd = radians[i];
if (hasCurrent && curIndex == i) {
curStartAngle = startA;
startA += rd;
continue;
}
paint.color = colors[i % colors.length];
paint.strokeWidth = paintWidth;
_drawArcWithCenter(canvas, paint,
center: center, radius: radius, startRadian: startA, sweepRadian: rd);
startA += rd;
}
if (hasEnd) {
startA = startAngle;
paint.strokeWidth = paintWidth;
for (int i = 0; i < radians.length; i++) {
var rd = radians[i];
if (hasCurrent && curIndex == i) {
startA += rd;
continue;
}
paint.color = colors[i % colors.length];
paint.strokeWidth = paintWidth;
_drawArcTwoPoint(canvas, paint,
center: center,
radius: radius,
startRadian: startA,
sweepRadian: rd,
hasEndArc: true);
startA += rd;
}
}

if (hasCurrent) {
paint.color = colors[curIndex % colors.length];
paint.strokeWidth = curPaintWidth;
paint.style = PaintingStyle.stroke;
_drawArcWithCenter(canvas, paint,
center: center,
radius: radius,
startRadian: curStartAngle,
sweepRadian: radians[curIndex]);
}
if (hasCurrent && hasEnd) {
var rd = radians[curIndex % radians.length];
paint.color = colors[curIndex % colors.length];
paint.strokeWidth = curPaintWidth;
paint.style = PaintingStyle.fill;
_drawArcTwoPoint(canvas, paint,
center: center,
radius: radius,
startRadian: curStartAngle,
sweepRadian: rd,
hasEndArc: true,
hasStartArc: true);
}
}

5. Use our function.

Just in our void paint(canvas,size) function, use our function above. Just like follow.

void paint(Canvas canvas, Size size) {
//580*648
if (size.width > 1.0 && size.height > 1.0) {
print(">1.9");
_sizeUtil.logicSize = size;
}
var paint = Paint()
..style = PaintingStyle.fill
..color = BLUE_NORMAL
..strokeWidth = 2.0
..isAntiAlias = true;
paint.color = Colors.grey[900];
// canvas.drawCircle(
// Offset(_sizeUtil.getAxisX(250), _sizeUtil.getAxisY(250.0)),
// _sizeUtil.getAxisBoth(200.0),
// paint);
paint.color = RED_DARK1;
paint.strokeWidth = 20;
paint.style = PaintingStyle.stroke;
var center = Offset(
_sizeUtil.getAxisX(250.0),
_sizeUtil.getAxisY(250.0),
);
var radius = _sizeUtil.getAxisBoth(200);
_drawArcGroup(
canvas,
center: center,
radius: radius,
sources: [1, 2, 1, 2, 1, 2, 1, 2, 1, 2],
colors: [BLUE_DARK1, RED_DARK1, BLUE_DARK2, GREEN_NORMAL, YELLOW_NORMAL],
paintWidth: 50.0,
startAngle: 0.0,
hasEnd: true,
hasCurrent: false,
curPaintWidth: 30.0,
curIndex: 1,
);
canvas.save();
canvas.restore();
}
https://cdn-images-1.medium.com/max/1200/1*xngtkWTk8UPnHeWoJy8AGQ.png" src="https://cdn-images-1.medium.com/max/1200/1*xngtkWTk8UPnHeWoJy8AGQ.png" style="border: 0px; display: block; position: absolute; top: 0px; left: 0px; width: 603px; height: 604.802px; margin: auto; z-index: 100; visibility: visible; opacity: 1; backface-visibility: hidden; transition: visibility 0s linear 0s, opacity 0.4s ease 0s;">

If you do not want the round angle, just change the hasEnd=false ,if you want show the someone to large, you should set harCurrent=ture and assign curPaintWidth a value of you like. The curIndex is for which one should be set. For example, we change value as below.

_drawArcGroup(
canvas,
center: center,
radius: radius,
sources: [1, 2, 1, 2, 1, 2, ],
colors: [BLUE_DARK1, RED_DARK1, BLUE_DARK2, GREEN_NORMAL, YELLOW_NORMAL],
paintWidth: 50.0,
startAngle: 0.0,
hasEnd: false,
hasCurrent: true,
curPaintWidth: 60.0,
curIndex: 1,
);

The result.

https://cdn-images-1.medium.com/max/1200/1*TctRj1MOIGPQq6qyEIaEBQ.png" src="https://cdn-images-1.medium.com/max/1200/1*TctRj1MOIGPQq6qyEIaEBQ.png" style="border: 0px; display: block; position: absolute; top: 0px; left: 0px; width: 603px; height: 616.865px; margin: auto; z-index: 100; visibility: visible; opacity: 1; backface-visibility: hidden; transition: visibility 0s linear 0s, opacity 0.4s ease 0s;">

The other param is for your research. Such as modifying its scale.

Conclusion

In this tutorial, we can draw the pie chart in the flutter.

  1. The principle of the arc with a round angle.
  2. Draw the arc and two circles.
  3. Define a function to draw a pie chart.
  4. Use the pie chart with the different values of the params.

The whole project, if you like, thanks for a star in the GitHub: https://github.com/FlutterOpen/flutter-canvas

The End

Developer: https://github.com/nb312

facebook page: https://www.facebook.com/flutteropen

Thanks for your reading, you can follow the Flutter Open.



Tags:








0 Comments
Login to comment.
Recent Comments

Be the first to Comment. You can ask a Query or Share your toughts or Just say thanks.


© 2018 - Fluttercentral | Email to me - seven.srikanth@gmail.com