Kevin Yang
Kevin Yang

Reputation: 727

Flutter) How to draw a diagonal line from the canvas with a dashed line?

I'm going to draw lines using canvas. I want to draw a dashed line like the image below.

I succeeded in drawing a dashed line with two points with the same Y-axis with the following code.

  void _drawDashedLine(
    Canvas canvas,
    Paint paint,
    Size size,
    Offset p1,
    Offset p2,
  ) {
    // dashed width and distance
    const int dashWidth = 5;
    const int dashSpace = 5;

    double startX = p1.dx;
    double startY = p1.dy;

    while (startX < p2.dx) {
      canvas.drawLine(
          Offset(startX, startY), Offset(startX + dashWidth, startY), paint);
      startX += dashWidth + dashSpace;
    }
  }

However, I'm failed to draw a diagonal line like the image below (the blue dot in the image is p1, p2).

This is the code I tried.

  void _drawDashedLine(
    Canvas canvas,
    Paint paint,
    Size size,
    Offset p1,
    Offset p2,
  ) {
    const int dashWidth = 5;
    const int dashSpace = 5;

    double startX = p1.dx;
    double startY = p1.dy;

    while (startX < p2.dx) {
      canvas.drawLine(Offset(startX, startY),
          Offset(startX + dashWidth, startY + dashWidth), paint);
      startX += dashWidth + dashSpace;
      startY += dashWidth + dashSpace;
    }
  }

This always changes the value of the Y-axis to be constant, so that it is drawn at a completely different angle.

I think I should calculate the Y-axis by the angle of the two points p1, p2, so can I know how to do this?

enter image description here

Upvotes: 0

Views: 1170

Answers (1)

obscure
obscure

Reputation: 12891

As you already guessed, we need to determine the angle formed by the two points p1 and p2 first. The dart's math library is our little helper here. Let's say we have the points

final p1 = Offset(50, 50);
final p2 = Offset(250, 150);

and feed the difference between the two points horizontal and vertical position to the math.atan2() method, we get the angle in radians

final dX = p2.dx - p1.dx;
final dY = p2.dy - p1.dy;
final angle = math.atan2(dY, dX);

The second step is calculating the actual width of the line. If it's a simple horizontal or vertical line things are quite simple, if it's at an angle which is not a multiple of 90° things are - a bit - more complicated. If we add two 'virtual' lines to our line to form a right-triangle, we can use the Pythagorean theorem (a^2+b^2=c^2) to calculate the length of the line .

final totalLength = math.sqrt(math.pow(dX, 2) + math.pow(dY, 2));

With this two steps we're ready to go. Starting from p1 we move into the direction of p2, sum up the segments we already draw and if it exceeds totalLength our line is complete.

  void _drawDashedLine(
    Canvas canvas,
    Paint paint,
    Offset p1,
    Offset p2,
  ) {
    const int dashWidth = 5;
    const int dashSpace = 5;

    final dX = p2.dx - p1.dx;
    final dY = p2.dy - p1.dy;
    final angle = math.atan2(dY, dX);
    final totalLength = math.sqrt(math.pow(dX, 2) + math.pow(dY, 2));

    double drawnLength = 0.0;
    final cos = math.cos(angle);
    final sin = math.sin(angle);

    while (drawnLength < totalLength) {
      canvas.drawLine(
          Offset(p1.dx + cos * drawnLength, p1.dy + sin * drawnLength),
          Offset(p1.dx + cos * (drawnLength + dashWidth),
              p1.dy + sin * (drawnLength + dashWidth)),
          paint);

      drawnLength += dashWidth + dashSpace;
    }
  }

Upvotes: 2

Related Questions