【问题标题】:How to draw a curved line between 2 points on canvas?如何在画布上的两点之间绘制曲线?
【发布时间】:2023-04-03 01:24:01
【问题描述】:

我从网络上的示例中尝试了很多不同的方法,但我似乎无法让它发挥作用。我正在尝试制作一种在画布上的 2 个点之间绘制曲线的方法。曲线应由半径参数定义。

以下是我当前的代码。

public OverlayBuilder drawCurvedArrow(int startX, int startY, int endX, int endY, int curveRadius, int padding, int color) {
    PointF mPoint1 = new PointF(startX, startY);
    PointF mPoint2 = new PointF(endX, endY);
    Paint paint  = new Paint();
    paint.setAntiAlias(true);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(12);
    paint.setColor(color);
    Path myPath = new Path();

    myPath.moveTo(startX, startY);
    myPath.quadTo(mPoint1.x, mPoint1.y, mPoint2.x, mPoint2.y);
    canvas.drawPath(myPath, paint);

    return this;
}

编辑

问题是我不知道如何弯曲画布上绘制的线条。

【问题讨论】:

  • 试试canvas.drawArc()
  • 你的意思是要在两点之间画一个圆弧?

标签: android canvas paint


【解决方案1】:

我自己找到了解决问题的方法。尽管有一些很好的答案,但它们并不是我特定问题的准确解决方案。

这是我所做的:

  • 找到两个给定点之间的点
  • 计算出两点之间的 90 度角
  • 使用之前计算的度数从中间点计算点 X 像素。
  • 在这 3 个点上使用了“path.cubicTo”(同时采用负值和正值来确定线条应该弯曲的方向)。

如果其他人遇到同样的问题,这是我的代码:

public OverlayBuilder drawCurvedArrow(int x1, int y1, int x2, int y2, int curveRadius, int color, int lineWidth) {

    Paint paint  = new Paint();
    paint.setAntiAlias(true);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(lineWidth);
    paint.setColor(ContextCompat.getColor(context, color));

    final Path path = new Path();
    int midX            = x1 + ((x2 - x1) / 2);
    int midY            = y1 + ((y2 - y1) / 2);
    float xDiff         = midX - x1;
    float yDiff         = midY - y1;
    double angle        = (Math.atan2(yDiff, xDiff) * (180 / Math.PI)) - 90;
    double angleRadians = Math.toRadians(angle);
    float pointX        = (float) (midX + curveRadius * Math.cos(angleRadians));
    float pointY        = (float) (midY + curveRadius * Math.sin(angleRadians));

    path.moveTo(x1, y1);
    path.cubicTo(x1,y1,pointX, pointY, x2, y2);
    canvas.drawPath(path, paint);

    return this;
}

以下是实现的示例:

【讨论】:

  • 非常感谢您提供开箱即用的工作方法,无需先调整 100 个变量
【解决方案2】:

我认为您为此目的使用了错误的方法,我可以建议的solutions 之一如下

float radius = 20;
final RectF oval = new RectF();
oval.set(point1.x - radius, point1.y - radius, point1.x + radius, point1.y+   radius);
Path myPath = new Path();
myPath.arcTo(oval, startAngle, -(float) sweepAngle, true);

你需要计算 startAngle

int startAngle = (int) (180 / Math.PI * Math.atan2(point.y - point1.y, point.x - point1.x));

对于sweepAngle,您可以找到详细描述here

【讨论】:

  • 谢谢!我在另一篇文章中看到了这个例子。什么是sweepAngle?我应该以某种方式计算它的价值吗?
  • 好的,我会研究一下.. 嗯,在 startAngle 的计算中,变量点是什么?代码的第一个sn-p中的point1是什么?哪个是起点,哪个是终点?
  • 非常感谢您的帮助,非常感谢。但是,我找到了解决我的特定问题的方法。
【解决方案3】:

假设你有两个点 mPoint1 和 mPoint2

int w=canvas.getWidth();
int h=canvas.getHeight();
int w_2= (w / 2);
int h_2= (h / 2);
PointF mPoint1 = new PointF(0, 0); //starts at canvas left top
PointF mPoint2 = new PointF(w_2, h_2);//mid of the canvas
Path drawPath1 =drawCurve(mPoint1, mPoint2);
canvas.drawPath(drawPath1, paint);

画线的方法

private Path drawCurve(PointF mPointa, PointF mPointb) {
            Path myPath = new Path();
            myPath.moveTo(mPointa.x, mPointa.y);
            final float x2 = (mPointb.x + mPointa.x) / 3;
            final float y2 = (mPointb.y + mPointa.y) / 3;
            myPath.quadTo(x2, y2, mPointb.x, mPointb.y);
            return myPath;
}

【讨论】:

  • 感谢您的回答@Stallion。在您提供的代码中,定义半径的值在哪里?
  • 我很久以前就做过这个,你可以尝试将 3 更改为不同的值(2,3 或 4)吗? (mPointb.x + mPointa.x) / 变量
  • 我试过了。如果设置为 2 它只是一条直线。如果设置为更高的值,则会绘制峰值形状。
  • 嗯,好吧..问题是我希望它“从线条的中间弯曲。然后我想确定它应该弯曲多少。像这样:pasteboard.co/1bt6SF4x.png
  • 非常感谢您的帮助,非常感谢。但是,我找到了解决我的特定问题的方法。
猜你喜欢
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-19
  • 2022-08-22
  • 1970-01-01
相关资源
最近更新 更多