如何在画布上的两点之间绘制圆弧?

问题描述 投票:44回答:6

我在画布上有两个点,现在我可以通过使用在这些点之间绘制一条线,如下图所示

这段代码canvas.drawLine(p1.x, p1.y, p2.x, p2.y, paint);

我想画两点之间的弧线,如下图所示。

我怎么画这样的。

android android-canvas ondraw
6个回答
47
投票

最后我从这段代码中得到了解决方案:

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));

在这里,qazxsw poi表示您想要开始绘制Arc的位置。 qazxsw poi表示两条线之间的角度。我们必须通过使用像我的问题图像中的蓝点这样的两个点来计算。


19
投票

做这样的事情:

point1

4
投票

我试图做一些不同的事情,而这一切都是关于计算扫描和开始角度。

我想要显示一个圆弧,表示从上到下的圆圈上的进度。

所以我有0 ... 100的进度值,我希望显示一个从上到下开始的弧,当进度为100时填充圆圈。

要计算sweepAngle,我使用:

sweepAngle

接下来是计算startAngle

@Override
protected void onDraw(Canvas canvas) {      
    Paint p = new Paint();
    RectF rectF = new RectF(50, 20, 100, 80);
    p.setColor(Color.BLACK);
    canvas.drawArc (rectF, 90, 45, true, p);
}

Start Angle以这种方式计算,因为:

  1. 它始终从左侧开始,从上到下开始。所以顶部的起始角度等于270(注意它顺时针方向和0 = 3点,所以12点钟等于270度)
  2. 接下来我想计算离开我的起点(270)多远,并且这样做我只计算一半的扫掠角,因为只有一半的弧在左侧而另一半在右边。

所以考虑到我有25%的进步

    int sweepAngle = (int) (360 * (getProgress() / 100.f));

如果你想从其他方面(从左到右,从右到左等)进行进度,你只需要在开始角度时替换270。


0
投票

绘制弧的样本。

    int startAngle = 270 - sweepAngle / 2;

0
投票

一个简单的解决方案被Langkiller建议sweepAngle = 90 degrees (90 degrees is quarter of a circle) start angle = 225 (45 degrees away from 270) 。这绘制了从起点到控制点到终点的立方线。

public static Bitmap clipRoundedCorner(Bitmap bitmap, float r, boolean tr, boolean tl, boolean bl, boolean br)
{
    int W = bitmap.getWidth();
    int H = bitmap.getHeight();

    if (r < 0)
        r = 0;

    int smallLeg = W;

    if(H < W )
        smallLeg = H;

    if (r > smallLeg)
        r = smallLeg / 2;

    float lineStop = r/2;

    Path path = new Path();
    path.moveTo(0,0);

    if(tr)
    {
        path.moveTo(0, lineStop);
        path.arcTo(new RectF(0,0, r,r), 180, 90, false);
    }

    path.lineTo(W-lineStop, 0);

    if(tl)
        path.arcTo(new RectF(W-r,0, W,r), 270, 90, false);
    else
        path.lineTo(W, 0);

    path.lineTo(W, H-lineStop);

    if(bl)
        path.arcTo(new RectF(W-r,H-r, W,H), 0, 90, false);
    else
        path.lineTo(W, H);

    path.lineTo(lineStop, H);

    if(br)
        path.arcTo(new RectF(0,H-r, r,H), 90, 90, false);
    else
        path.lineTo(0,H);

    if(tr)
        path.lineTo(0,lineStop);
    else
        path.lineTo(0,0);


    Bitmap output = Bitmap.createBitmap(W, H, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    paint.setColor(Color.BLACK);
    canvas.drawPath(path, paint);

    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    canvas.drawBitmap(bitmap, 0, 0, paint);

    return output;
}

0
投票

我可能迟到了,但我得到了更多的信息。

here之后,有两种方法可以解决这个问题

public void drawArc(RectF oval,float startAngle,float sweepAngle,boolean useCenter,Paint paint)

public void drawArc(float left,float top,float right,float bottom,float startAngle,float sweepAngle,boolean useCenter,Paint paint)

用法:

Path path = new Path();
float startX = 0;
float startY = 2;
float controlX = 2;
float controlY = 4;
float endX = 4
float endY = 2
conePath.cubicTo(startX, startY, controlX, controlY,endX, endY);

Paint paint = new Paint();
paint.setARGB(200, 62, 90, 177);
paint.setStyle(Paint.Style.FILL);

canvas.drawPath(path, paint)

扫描角度不过是顺时针绘制的扇形角度,例如。以下代码

Android Lollipop

结果将如下所示

RectF rectF = new RectF(left, top, right, bottom); // method 1 canvas.drawArc (rectF, 90, 45, true, paints[0]); // method 2 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { canvas.drawArc (left, top, right, bottom, 0, 45, true, paints[1]); }

在定义Paths的帮助下,然后在onDraw方法中迭代它们就可以实现同样的效果,如下面的代码片段所示:

private void drawArcs(Canvas canvas) {
    RectF rectF = new RectF(left, top, right, bottom);

    // white arc
    canvas.drawArc (rectF, 90, 45, true,  paints[0]);

    // Green arc
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        canvas.drawArc (left, top, right, bottom, 0, 45, true, paints[1]);
    }

    // Red stroked arc
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        canvas.drawArc (left, top, right, bottom, 180, 45, true,  paints[2]);
    }
}

完整源代码:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.