This article will serve as a series of original portals:

  • Learn the basics of Flutter Canvas
  • Drawing of Flutter Canvas learning
  • The graph transformation of Flutter canvas learning

Based on Flutter version: 2.0.3

preface

The previous article covered the basic concepts related to the Flutter CustomPaint component. This article focuses on the Canvas based drawing capabilities.

Plot points – drawPoints

void drawPoints(PointMode pointMode, List points, Paint paint)

  • PointMode: Sets points and lines
    • PointMode. Points set point
    • Pointmode. lines Two links between two points, if passedpointsIt’s odd, and the last point will be ignored
    • Pointmode. polygon joins all the points together
  • Points: aOffsetArray. I can draw multiple points

If paint sets strokeCap = strokecap. round, the dots will be round. (The same applies to any other API, which follows the brush property.)

import 'dart:ui' as ui;
/ /...
/ / draw pointPaint paint = Paint() .. color = Colors.red .. strokeWidth =20;
canvas.drawPoints(
    ui.PointMode.points,
    [
      Offset(100.100),
      Offset(250.180),
      Offset(200.300),
    ],
    paint);
// Set the endpoints to circles
paint.strokeCap = StrokeCap.round;
canvas.drawPoints(ui.PointMode.points, [Offset(100.200)], paint);
Copy the code

If the input parameters are set toPointMode.polygon

Draw a line segment -drawLine

void drawLine(Offset p1, Offset p2, Paint paint)

  • P1,p2 is the position of the two endpoints
canvas.drawLine(Offset(100.100), Offset(250.180), paint);
Copy the code

DrawLine can only be used to draw a line segment. DrawPoints can be used to draw a line segment

canvas.drawPoints(
  ui.PointMode.lines,
  [
    Offset(100.100),
    Offset(250.180),
  ],
  paint);
Copy the code

Draw the region -drawRect

Because Rect is used in a lot of methods, I’m going to start with the drawRect method.

Rect means to draw a rectangular region, it has no constructors, it just has static methods

fromLTRB

Rect Rect.fromLTRB(double left, double top, double right, double bottom)

This method is the parent of all methods of this class, and is used to implement all other methods

  • Left: distance between the left of the rectangle and the left of the canvas
  • Top: distance between the top of the rectangle and the top of the canvas
  • Right: distance between the right side of the rectangle and the left side of the canvas
  • Bottom: Distance from bottom of rectangle to top of canvas

Here’s an example

canvas.drawRect(Rect.fromLTRB(50.50.350.350), paint);
Copy the code

fromCenter

Rect.fromCenter({Offset center, double width, double height})

Draw a rectangle

  • Center: the position of the center of a rectangle
  • Width: the width of a rectangle
  • Height: the height of a rectangle
canvas.drawRect(
      Rect.fromCenter(center: Offset(200.300), width: 250, height: 350), paint);
Copy the code

fromCircle

Rect.fromCircle({Offset center, double radius})

Draw a square

  • Center: the position of the center of a square
  • Radius: distance between four sides of a square and the center point
canvas.drawRect(
        Rect.fromCircle(center: Offset(200.300), radius: 150), paint);
Copy the code

fromPoints

Rect.fromPoints(Offset a, Offset b)

Use two points to define a rectangle

  • A: The top left corner of the rectangle
  • B: The lower right corner of the rectangle
canvas.drawRect(Rect.fromPoints(Offset(100.200), Offset(300.400)), paint);
Copy the code

Draw rounded rectangle -RRect

void drawRRect(RRect rrect, Paint paint)

RRect is used to draw rectangles with rounded corners. It draws the same position as rect. fromLTRB, but with an extra parameter to set rounded corners.

RRect rRect = RRect.fromLTRBR(100.100.350.350, Radius.circular(30));
canvas.drawRRect(rRect, paint);
Copy the code

Draw round – drawOval

void drawOval(Rect rect, Paint paint)

DrawOval is used to draw circles

Rect pRect = Rect.fromLTRB(50.150.400.350);
// To differentiate, draw a rectangle first
canvas.drawRect(pRect, paint);
paint.color = Colors.yellow;
// Draw the ellipse
canvas.drawOval(pRect, paint);
Copy the code

The yellow area is the drawn circle, which was drawn in Rect

Draw arc-DRAwarc

drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)

Draw an arc. The useCenter indicates whether to draw the center point to both sides of the arc

Rect rect = Rect.fromCircle(
    center: Offset(size.width / 2, size.height / 2), radius: 100);
// For easy viewing, draw the region as well
canvas.drawRect(rect);
// Draw an arc
canvas.drawArc(rect, 90 * (pi / 180), 90 * (pi / 180), false, paint);
Copy the code

For an introduction to angles, see my previous article

Draw a path -drawPath

void drawPath(Path path, Paint paint)

DrawPath is a very powerful method. It is the essence of canvas and can be used for almost any other drawing. Other methods can be briefly looked at, this must focus on learning to understand. Here’s what it can do

Draw simple shapes

Path path = new Path();
path.moveTo(100.100);
path.lineTo(200.200);
path.lineTo(250.180);
path.lineTo(200.300);
path.lineTo(100.200);
canvas.drawPath(path, paint);
Copy the code

There are many methods for Path, and the following are common ones

moveTo

Sets the starting position of the brush

lineTo

The next position you draw, you pass in the actual position relative to the coordinate system, and you move it in code order

relativeLineTo

Similar to lineTo, but passing in a position relative to the origin of the previous point, for example, the previous point was at (100,100) and passing in (150,150). If you use lineTo to achieve the same effect, you should pass in (250,250). It has a lot of methods, and the relative method is the same principle, so THE relative-method will not be explained.

arcTo

Draw an arc

void arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo)

This method is similar to drawArc in that the first three arguments are the same, with the last argument indicating whether to connect to a line segment drawn before path (e.g., by lineTo). False indicates connection, and true indicates disconnection.

quadraticBezierTo

Draw a second-order Bezier curve

void quadraticBezierTo(double x1, double y1, double x2, double y2)

What is the Searle curve, as wikipedia describes it

In the field of numerical analysis of mathematics, Bezier curve (English: Bezier curve) is an important parametric curve in computer graphics. The generalized Bezier curves of higher dimensions are called Bezier surfaces, of which bezier triangle is a special instance.

It is drawn as follows (from Wikipedia):

The establishment of a second-order Bezier curve requires three points, P0 starting point, P1 process point and P2 ending point

When using quadraticBezierTo to draw, we can use moveTo to determine the starting point P0, x1 and y1 to determine P1, x2 and y2 to determine P2

var path = Path();
path.moveTo(50.500);
path.quadraticBezierTo(100.300.350.300);
canvas.drawPath(path1, paint);
Copy the code

The blue coordinate system and yellow points are the auxiliary lines I draw, and the red is the result of the above code execution

conicTo

void conicTo(double x1, double y1, double x2, double y2, double w

It also plots second-order bezier curves, but compared with the quadraticBezierTo, it has an extra parameter w to control the radian of the curve. When w < 1, the curve radian is smaller; When w = 1, it has the same effect as quadraticBezierTo; When w is greater than 1, it’s going to be more radians

path.conicTo(100.300.350.300.3);
Copy the code

cubicTo

Draw third-order Bezier curves

void cubicTo(double x1, double y1, double x2, double y2, double x3, double y3)

The third-order Bezier curve has only one more point than the second-order Bezier curve, and the principle is similar

path.moveTo(50.500);
path.cubicTo(50.200.300.400.350.150);
Copy the code

addRect

Draws a rectangular region

path.addRect(Rect.fromLTRB(50.50.350.350));
Copy the code

This effect is the same as in the first drawRect example above

addRRect

Draw a rectangle with rounded corners

RRect rRect = RRect.fromLTRBR(100.100.350.350, Radius.circular(30));
path.addRRect(rRect);
Copy the code

The above code works just like drawRRect

addArc

Draw an arc

Path path = new Path();
// Draw a rectangle
Rect rect = Rect.fromCircle(
    center: Offset(size.width / 2, size.height / 2), radius: 100);
canvas.drawRect(rect, paint);
// Draw an arc over the rectangular area
path.addArc(rect, 90 * (pi / 180), 90 * (pi / 180));
paint.color = Colors.red;
canvas.drawPath(path, paint);
Copy the code

The above code has the same effect as drawArc

Canvas. DrawArc, path.addArc, and path.arcTo(when forceMoveTo is true) all draw the same arc effect

addOval

Draw an ellipse

Rect pRect = Rect.fromLTRB(50.150.400.350);
path.addOval(pRect);
canvas.drawPath(path, paint);
Copy the code

Code effect is the same as drawOval

addPolygon

Draw line segments by points

void addPolygon(List points, bool close)

  • Point: The point where multiple points are passed in
  • Close: when true, the last point is connected to the first point
Path path = new Path();
path.addPolygon([
      Offset(100.100),
      Offset(250.180),
      Offset(200.300)],false);
canvas.drawPath(path, paint);
Copy the code

computeMetrics

PathMetrics computeMetrics({bool forceClosed = false})

The computeMetrics method is used to return a snapshot of a previously drawn path. When we draw paths with moveTo, lineTo, arcTo, conicTo, etc., we can use this to draw only part of them.

Such as:

var path = Path();
path.moveTo(50.500);
path.cubicTo(50.200.300.400.350.150);
// Set the full drawing to red
paint.color = Colors.red;
canvas.drawPath(path, paint);
ui.PathMetrics pathMetrics = path.computeMetrics();
// Draw half
var progress = 0.5;
// Change the color to purple for differentiation
paint.color = Colors.deepPurple;
for (ui.PathMetric pathMetric in pathMetrics) {
  Path extractPath = pathMetric.extractPath(
    0.0,
    pathMetric.length * progress,
  );
  canvas.drawPath(extractPath, paint);
}
Copy the code

extendWithPath

void extendWithPath(Path path, Offset offset, {Float64List matrix4})

Use to copy a previously drawn path and shift the position of offset. The original path will be connected to the new path. Matrix4 is a 4D matrix processing of new paths.

var path = Path();
path.moveTo(50.500);
// Draw a third-order Bezier curve
path.cubicTo(50.200.300.400.350.150);
/ / processing
path.extendWithPath(path, Offset(50.30),
    matrix4: Float64List.fromList(
        [1.0.0.0.1..1.0.0.0.0.1.0.0.0.0.2]));
canvas.drawPath(path, paint);
Copy the code

The part circled in blue is the effect of the method

shift

Path shift(Offset offset)

Can be used to copy the previously drawn Path and shift the offset position to return Path. Unlike extendWithPath, this method simply copies the path and does not attach to the original path.

var path = Path();
path.moveTo(50.500);
path.cubicTo(50.200.300.400.350.150);

// The original graph is red
paint.color = Colors.red;
canvas.drawPath(path, paint);
// Copy the original path and translate it
var path2 = path.shift(Offset(50.20));
paint.color = Colors.yellow;
canvas.drawPath(path2, paint);
Copy the code

close

void close()

Use to connect the start and end of a path

conclusion

After learning above, we know that in fact, multiple drawing methods can achieve the same effect

Plot points

  • canvas.drawPoints
  • path.addPolygon

Draw a straight line

  • DrawPoints and participationPointMode.polygonorPointMode.lines
  • drawLine
  • path.lineTo

Draw the arc

  • canvas.drawArc
  • path.addArc

The next chapter will introduce Canvas graph transformation, such as rotation, translation, zooming, etc. If you are interested, please pay attention

  • zhihu
  • Personal blog
  • GitHub