1. Draw Path (Path path, Paint paint)
Path has the following main methods:
The method of directly describing a path can also be subdivided into two groups: adding subgraphics and drawing lines (straight lines or curves)
-
addXXX() - Add subgraphics (since such method parameters are the same as the simple graphics described above, they will not be redundant)
- addArc(Rect oval, double startAngle, double sweepAngle) - Add Arc
- addOval(Rect oval) - Add a circle
- AddPolygon (List<Offset> points, bool close) - Add a polygon described by a set of points
- addRect(Rect rect) - Add Rectangle
- addRRect(Rect rect) - Add rounded rectangle
- addPath(Path path, Offset offset) - Add subpath
-
XXXTo() - Draw lines (straight or curved)
This method draws graphics by describing paths, probably in this way:
Path _path = Path(); @override void paint(Canvas canvas, Size size) { _paint.style = PaintingStyle.stroke; // Line drawing mode _path.addArc(new Rect.fromLTWH(50, 50, 50, 50), 135.0 * (pi / 180.0), 225.0 * (pi / 180.0)); _path.addArc(new Rect.fromLTWH(100, 50, 50, 50), 180.0 * (pi / 180.0), 225.0 * (pi / 180.0)); _path.lineTo(100, 140); _path.lineTo(58, 93); canvas.drawPath(_path, _paint); }
-
Draw a straight line - lineTo(double x, double y) / relativelineTo(double x, double y) to the target location
Draw a straight line from the current location to the target location, where x and y are the coordinates of the target location.The difference between the two methods is that the parameters of lineTo(x, y) are absolute coordinates, while the parameters of relativeLineTo(x, y) are relative coordinates relative to the current location; -
_paint.style = PaintingStyle.stroke; // Line drawing mode _path.lineTo(100, 100); // From the current location (0, 0) towards (100, 100) Draw a straight line _path.relativeLineTo(100, 0); // From the current location (100, 100) Draw 100 pixels to the right canvas.drawPath(_path, _paint);
-
Draw a second order Bezier curve - quadratic BezierTo (double x1, double y1, double x2, double y2) / relativeQuadratic BezierTo (double x1, double y1, double x2, double y2)
x1, y1 is the coordinate of the control point; x2, y2 is the coordinate of the end point; relativeQuadratic BezierTo() is the relative straight line method above
_paint.style = PaintingStyle.stroke; // Line drawing mode List<Offset> points = new List(); points.add(new Offset(100, 50)); // Draw control point position for easy understanding canvas.drawPoints(PointMode.points, points, _paint); _path.moveTo(0, 100); // Move starting point to (0),100) _path.quadraticBezierTo(100, 50, 200, 100); canvas.drawPath(_path, _paint);
-
Draw a third order Bezier curve - cubicTo(double x1, double y1, double x2, double y2, double x3, double y3) / relativeCubicTo(double x1, double y1, double x2, double y2, double x3, double y3)
Same as the second-order Bezier curve of the quadratic BezierTo() and relativeQuadratic BezierTo() above, let alone say more.
@override void paint(Canvas canvas, Size size) { Path path = new Path()..moveTo(100.0, 100.0); List<Offset> points = new List(); points.add(new Offset(100, 50)); // Draw control point position for easy understanding canvas.drawPoints(PointMode.points, points, _paint); path.moveTo(0, 100); // Move starting point to (0),100) path.cubicTo(100, 100, 200, 200, 300, 300); canvas.drawPath(path, _paint); }
-
Move to a point - moveTo(double x, double y) / relativeMoveTo(double dx, double dy)
Both straight lines and Bezier curves start from the current position and cannot be specified.However, you can indirectly set the starting point for these methods by changing the current location through moveTo(x, y) or relativeMoveTo(x, y).
_paint.style = PaintingStyle.stroke; // Line drawing mode _path.moveTo(20, 40); // Move starting point to (20),40) _path.lineTo(80, 100); // Draw a line slash _path.moveTo(100, 40); // Move starting point to (100),20) _path.lineTo(100, 100); // Draw a line canvas.drawPath(_path, _paint);
But with the exception of arcTo(), this method does not start drawing from the current location
-
Draw Arc - arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo)
We are familiar with the first three parameters, and the last one means whether to drag the pen to the start or lift it to the start when drawing this arc.
_paint.style = PaintingStyle.stroke; // Line drawing mode _path.moveTo(20, 40); // Move starting point to (20),40) _path.lineTo(80, 100); // Draw a line slash _path.arcTo(new Rect.fromLTWH(60, 60, 100, 100), 0.0 * (pi / 180.0), 90.0 * (pi / 180.0), false); canvas.drawPath(_path, _paint);
Drag your pen:
Raise your pen:
-
Close the current path - close()
_paint.style = PaintingStyle.stroke; // Line drawing mode _path.moveTo(20, 40); // Move starting point to (20),20) _path.lineTo(80, 100); // Draw a line slash _path.arcTo(new Rect.fromLTWH(60, 60, 100, 100), 0.0 * (pi / 180.0), 90.0 * (pi / 180.0), false); _path.close(); // Close the current path canvas.drawPath(_path, _paint);
The drawing of Canvas graphics is almost complete here. When the graphics are simple, use drawCircle() drawRect() to draw directly; when the graphics are complex, use drawPath() to draw custom graphics.In addition, Canvas can draw pictures and text.
2. Picture - drawImage, Offset p, Paint paint / drawImageRect (Image image, Rect src, Rect dst, Paint paint)
-
System method
drawImage() Draws the width and height of the picture in pixels starting at the specified point, which is not commonly used because the size of the picture cannot be controlled; the first parameter is the image under the ui package, not the Image Widge
-
Usage method
Image can be obtained from the following code
ui.Image image; /** * Initialize Picture * Future<VoidCallback> initImage() async { image = await _loadImage("./assets/images/img.jpg"); return null; } /** * Get resource pictures from assets path */ Future<Image> _loadImage(String assets) async { final ByteData data = await rootBundle.load(assets); if (data == null) throw 'Unable to read data'; Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List()); FrameInfo frame = await codec.getNextFrame(); return frame.image; }
Then initialize in the initState() method (shouldRepaint() method must remember to return true otherwise it cannot be redrawn)
void initState() { super.initState(); painter.initImage().then((val) { setState(() { }); }); }
Finally, fill in the following code in the paint() method:
canvas.drawImage(image, new Offset(0, 0), _paint);
drawImageRect() is a common method; it mainly knows the second and third parameters:
- Rect src - The area of the original image, usually the width and height of the transmitted picture
- Rect dst - The area displayed by a picture. If the aspect ratio of the original image area is inconsistent with the display area, the original image will be stretched or compressed
canvas.drawImageRect(image, Offset(0.0, 0.0) & Size(image.width.toDouble(), image.height.toDouble()), Offset(0.0, 0.0) & Size(200, 200), _paint);
Normal ratio:
Stretch:
3. Draw Paragraph (Paragraph paragraph, Offset offset)
-
System method
drawParagraph(Paragraph paragraph, Offset offset)
-
Usage method
The code comment is clear, and there are five pieces of text circled here
for (int i = 0; i<5 ;i++){ // Create a new paragraph builder and fill in the basic text information; ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle( textAlign: TextAlign.left, fontWeight: FontWeight.w300, fontStyle: FontStyle.normal, fontSize: 15.0+i, )); pb.pushStyle(ui.TextStyle(color: Colors.black87)); pb.addText('Flutter Unified Mobile End'); // Set width constraints for text ParagraphConstraints pc = ParagraphConstraints(width: 300); // You need to start here layout,Fill in the width constraint, otherwise it will not draw Paragraph paragraph = pb.build()..layout(pc); // Starting point of upper left corner of text Offset offset = Offset(50, 50+i*40.0); canvas.drawParagraph(paragraph, offset); }
-
Example
Reference resources: https://juejin.im/post/5c67a6a0f265da2dae510fa2#heading-14