The foreword 0.

A lot of people ask me how to draw dotted lines, but I have no need for this aspect, I do not care too much. Now that you think about it, drawing dashed lines through path measurements should be pretty simple. I will spare some space and write a handy dotted line path drawing tool, otherwise it is really quite laborious to draw an auxiliary line.


The painting tool dash_painter has been uploaded to pub:

  • Dev /packages/da…
  • Github address: github.com/toly1994328…
The rounded rectangle circular

1. Implementation of the drawing

In the following palette, I draw a line through a path, which is probably the most basic thing to draw. Now let’s see how we can do that and turn it into a dotted line.

class TolyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    canvas.translate(size.width / 2, size.height / 2); Paint paint = Paint().. style = PaintingStyle.stroke .. color=Colors.orangeAccent.. strokeWidth =2;

    Path path = Path();
    path.moveTo(- 100..0);
    path.lineTo(100.0);

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant TolyPainter oldDelegate) => false;
}
Copy the code

2. Draw a dotted line – Level1

For ease of administration and extension, you can separate the dashed object into a class DashPainter. So if you want to draw a dotted line, you have to specify the dotted line parameters, so let’s do a simple one. The single length and spacing of the dotted line are represented by step and span respectively. The following is a dotted line with step:20 and span: 10.

class DashPainter {
  final double step;
  final double span;

  const DashPainter({this.step = 2.this.span = 2});double get partLength => step + span;

  void paint(Canvas canvas, Path path, Paint paint) {
    final PathMetrics pms = path.computeMetrics();
    pms.forEach((PathMetric pm) {
      final int count = pm.length ~/ partLength;
      for (int i = 0; i < count; i++) {
        canvas.drawPath(
            pm.extractPath(partLength * i, partLength * i + step), paint);
      }
      final doubletail = pm.length % partLength; canvas.drawPath(pm.extractPath(pm.length-tail, pm.length), paint); }); }}Copy the code

The implementation logic is also very simple: computeMetrics the path, and then according to the number of copies traversal to draw the intercepted path. It is also very simple to use, as long as a sentence can be changed into virtual:

const DashPainter(span: 10, step: 20).paint(canvas, path, paint);
Copy the code

You can control the display of dashed lines by controlling the step and SPAN parameters.

step:6, span: 6 step:6, span: 4

In fact, at this point, you can make any path dotted, rounded rectangle and circle as follows:

final Path path = Path();
path.addRRect(RRect.fromRectAndRadius(
   Rect.fromCircle(center: Offset.zero, radius: 100),
   Radius.circular(20)));const DashPainter(span: 4, step: 9).paint(canvas, path, paint);
Copy the code
The rounded rectangle circular

2. Draw a dotted line – Level2

In addition to dotted lines, sometimes there is a requirement for underlined lines, as follows

  • Single point line:

  • Two point line:

  • Three-point line:


Add pointCount and pointWidth to the pointCount and pointWidth attributes, respectively. The pointLineLength length should be lengthened according to pointCount and pointWidth, as shown below:

class DashPainter {
  const DashPainter({
    this.step = 2.this.span = 2.this.pointCount = 0.this.pointWidth,
  });

  final double step;
  final double span;
  final int pointCount;
  final double pointWidth;

  void paint(Canvas canvas, Path path, Paint paint) {
    final PathMetrics pms = path.computeMetrics();
    final double pointLineLength = pointWidth ?? paint.strokeWidth;
    final double partLength =
        step + span * (pointCount + 1) + pointCount * pointLineLength;

    pms.forEach((PathMetric pm) {
      final int count = pm.length ~/ partLength;
      for (int i = 0; i < count; i++) {
        canvas.drawPath(
            pm.extractPath(partLength * i, partLength * i + step), paint,);
        for (int j = 1; j <= pointCount; j++) {
          final start =
              partLength * i + step + span * j + pointLineLength * (j - 1); canvas.drawPath( pm.extractPath(start, start + pointLineLength), paint, ); }}final doubletail = pm.length % partLength; canvas.drawPath(pm.extractPath(pm.length - tail, pm.length), paint); }); }}Copy the code

This allows you to do cool things like dot lines and circles:

final Path path = Path();
path.moveTo(- 200..0);
path.lineTo(200.0);
path.moveTo(0.- 200.);
path.lineTo(0.200);
path.addOval(Rect.fromCircle(center: Offset.zero, radius: 100));
const DashPainter(
    span: 4./ / space
    step: 10./ / solid lines long
    pointCount: 2.// Number of dashes
    pointWidth: 2 // The dashes are long
).paint(canvas, path, paint);
Copy the code

3. Decoration drawing

Many people may not be able to customize their own artboards or simply want to use them. In fact, there are other places besides CustomPainter that have canvas. Such as Decoration. We can customize the decoration of DashDecoration for easy use. This is just a simple use to encapsulate the configuration properties.

class DashDecoration extends Decoration {

  @override
  BoxPainter createBoxPainter([onChanged]) => const DashBoxPainter();
}

class DashBoxPainter extends BoxPainter {
  final Color color;
  const DashBoxPainter({this.color});
  
  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    canvas.save();
    finalPaint paint = Paint() .. style = PaintingStyle.stroke .. color = Colors.orangeAccent .. strokeWidth =1;
    final Path path = Path();

    canvas.translate(
      offset.dx + configuration.size.width / 2,
      offset.dy + configuration.size.height / 2,);final Rect zone = Rect.fromCenter(
      center: Offset.zero,
      width: configuration.size.width,
      height: configuration.size.height,
    );

    path.addRRect(RRect.fromRectAndRadius(
      zone,
      Radius.circular(20)));const DashPainter(span: 4, step: 9).paint(canvas, path, paint); canvas.restore(); }}Copy the code

This property configuration is packaged in the library and can be used directly, as shown in the following implementation of a gradient single dotted line rounded dotted box.

Container(
  width: 100,
  height: 100,
  decoration: DashDecoration(
      pointWidth: 2,
      step: 5,
      pointCount: 1,
      radius: Radius.circular(15),
      gradient: SweepGradient(colors: [
        Colors.blue,
        Colors.red,
        Colors.yellow,
        Colors.green
      ])),
  child: Icon(
    Icons.add,
    color: Colors.orangeAccent,
    size: 40,),),Copy the code

This article ends here, this tool has a lot of room to optimize and expand, later sometimes or inspiration will continue to maintain, I hope to help you.