flutter)如何用画布制作箭线?

发布于 2025-02-09 10:08:23 字数 231 浏览 2 评论 0原文

我想在用画布的绘制线()绘制的线的末端(或两侧)放置箭头。

像这样

我能知道该怎么做吗?

I want to put an arrow at the end (or on both sides) of a line drawn with a drawLine() of canvas.

Like this

enter image description here

Can I know how to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羁拥 2025-02-16 10:08:23

实际上,这并不难 - 只涉及一点数学。

让我们有一条线并像这样设置油漆:

final paint = Paint()
  ..color = Colors.black
  ..strokeWidth = 2;

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

canvas.drawLine(p1, p2, paint); 

这将为我们提供:

“”

现在,如果我们将此行视为向量,我们记得向量有方向。为了获得方向,我们必须找到线路和末端之间的角度。可以使用DART的数学库的atan2函数来完成。

因此,导入数学库

导入'dart:数学'作为数学;

之后添加以下行

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

,让我们确定我们将要放在行结尾处的箭头的大小和角度:

final arrowSize = 15;
final arrowAngle=  25 * math.pi / 180;

剩下的一切实际上都在绘制箭头。这基本上是通过以正确角度绘制三角形的三角形来完成的。

final path = Path();

path.moveTo(p2.dx - arrowSize * math.cos(angle - arrowAngle),
    p2.dy - arrowSize * math.sin(angle - arrowAngle));
path.lineTo(p2.dx, p2.dy);
path.lineTo(p2.dx - arrowSize * math.cos(angle + arrowAngle),
    p2.dy - arrowSize * math.sin(angle + arrowAngle));
path.close();
canvas.drawPath(path, paint);

最终将给我们:

“”

That's actually not that hard to do - there's just a little math involved.

Let's have a line and paint set up like this:

final paint = Paint()
  ..color = Colors.black
  ..strokeWidth = 2;

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

canvas.drawLine(p1, p2, paint); 

this will give us:

Now if we think of this line as a vector, we remember a vector has a direction. To get the direction we must find the angle between the start and the end of the line. This can be done using the atan2 function of dart's math library.

So import the math library

import 'dart:math' as math;

and add the following lines

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

Afterwards let's determine a size and an angle for the arrow we're about to put at the end of the line:

final arrowSize = 15;
final arrowAngle=  25 * math.pi / 180;

Everything that's left is actually drawing the arrow. This is basically done by drawing a triangle at the proper angle the line is facing using a path.

final path = Path();

path.moveTo(p2.dx - arrowSize * math.cos(angle - arrowAngle),
    p2.dy - arrowSize * math.sin(angle - arrowAngle));
path.lineTo(p2.dx, p2.dy);
path.lineTo(p2.dx - arrowSize * math.cos(angle + arrowAngle),
    p2.dy - arrowSize * math.sin(angle + arrowAngle));
path.close();
canvas.drawPath(path, paint);

Which will finally give us:

故事和酒 2025-02-16 10:08:23

这是从晦涩的答案中得出的解决方案,从线上减去箭头的头部,因此不会伸出来:

  void drawArrow(Offset a, Offset b, Canvas canvas, Color color) {
    final paint = Paint()
      ..color = color
      ..strokeWidth = 2
      ..strokeCap = StrokeCap.round;
    const arrowSize = 10;
    const arrowAngle = pi / 6;

    final dX = b.dx - a.dx;
    final dY = b.dy - a.dy;
    final angle = atan2(dY, dX);

    // Recalculate b such that it's the end of the line minus the arrow.
    final Offset subtractedB = Offset(
      b.dx - (arrowSize - 2) * cos(angle),
      b.dy - (arrowSize - 2) * sin(angle),
    );

    canvas.drawLine(a, subtractedB, paint);
    final path = Path();

    path.moveTo(b.dx - arrowSize * cos(angle - arrowAngle),
        b.dy - arrowSize * sin(angle - arrowAngle));
    path.lineTo(b.dx, b.dy);
    path.lineTo(b.dx - arrowSize * cos(angle + arrowAngle),
        b.dy - arrowSize * sin(angle + arrowAngle));
    path.close();
    canvas.drawPath(path, paint);
  }

Here's a solution derived from obscure's answer to subtract the head of the arrow from the line so it does not stick out:

  void drawArrow(Offset a, Offset b, Canvas canvas, Color color) {
    final paint = Paint()
      ..color = color
      ..strokeWidth = 2
      ..strokeCap = StrokeCap.round;
    const arrowSize = 10;
    const arrowAngle = pi / 6;

    final dX = b.dx - a.dx;
    final dY = b.dy - a.dy;
    final angle = atan2(dY, dX);

    // Recalculate b such that it's the end of the line minus the arrow.
    final Offset subtractedB = Offset(
      b.dx - (arrowSize - 2) * cos(angle),
      b.dy - (arrowSize - 2) * sin(angle),
    );

    canvas.drawLine(a, subtractedB, paint);
    final path = Path();

    path.moveTo(b.dx - arrowSize * cos(angle - arrowAngle),
        b.dy - arrowSize * sin(angle - arrowAngle));
    path.lineTo(b.dx, b.dy);
    path.lineTo(b.dx - arrowSize * cos(angle + arrowAngle),
        b.dy - arrowSize * sin(angle + arrowAngle));
    path.close();
    canvas.drawPath(path, paint);
  }
等你爱我 2025-02-16 10:08:23

简单:

class ArrowPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.black
      ..strokeWidth = 2.0
      ..style = PaintingStyle.stroke;

    // Drawing the line
    Offset startPoint = Offset(size.width / 2, size.height);
    Offset endPoint = Offset(size.width / 2, 0);
    canvas.drawLine(startPoint, endPoint, paint);

    // Drawing the arrowhead
    double arrowSize = 10; // Size of the arrowhead
    double angle = math.pi / 6; // Angle of the arrowhead
    Path path = Path();
    path.moveTo(size.width / 2, 0);
    path.lineTo(size.width / 2 - arrowSize * math.cos(angle), arrowSize * math.sin(angle));
    path.moveTo(size.width / 2, 0);
    path.lineTo(size.width / 2 + arrowSize * math.cos(angle), arrowSize * math.sin(angle));

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

致电课:

CustomPaint(
            size: Size(10, 200), // Width and height of the arrow
            painter: ArrowPainter(),
            )

Simple:

class ArrowPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.black
      ..strokeWidth = 2.0
      ..style = PaintingStyle.stroke;

    // Drawing the line
    Offset startPoint = Offset(size.width / 2, size.height);
    Offset endPoint = Offset(size.width / 2, 0);
    canvas.drawLine(startPoint, endPoint, paint);

    // Drawing the arrowhead
    double arrowSize = 10; // Size of the arrowhead
    double angle = math.pi / 6; // Angle of the arrowhead
    Path path = Path();
    path.moveTo(size.width / 2, 0);
    path.lineTo(size.width / 2 - arrowSize * math.cos(angle), arrowSize * math.sin(angle));
    path.moveTo(size.width / 2, 0);
    path.lineTo(size.width / 2 + arrowSize * math.cos(angle), arrowSize * math.sin(angle));

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

Call the class:

CustomPaint(
            size: Size(10, 200), // Width and height of the arrow
            painter: ArrowPainter(),
            )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文