How to draw Arc between two points on the Canvas?

后端 未结 7 1198
渐次进展
渐次进展 2020-11-28 04:27

I have two points in the canvas, now I\'m able to draw a line between those points like this below image by using

This code canvas.drawLine(p1.x, p1.y, p2.x,

相关标签:
7条回答
  • 2020-11-28 04:42

    I was trying to do something a little different and it's all about calculating sweep and start angles.

    I wanted to show an arc that represents progress on a circle that goes from top to bottom.

    So I had progress value from 0...100 and I want to show an arc that start from top to bottom to fill the circle when the progress is 100.

    To calculate the sweepAngle I use:

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

    Next is to calculate the startAngle

        int startAngle = 270 - sweepAngle / 2;
    

    Start Angle is calculated this way because:

    1. It's always going to start from the left side, starting from the top to bottom. So starting angle at the top equals 270 (Note that it goes clockwise and 0 = 3 o'clock, so 12 o'clock equals 270 degrees)
    2. Next I want to calculate how far I'm going to get away from my starting point (270) and to do that I only calculate half of the sweep angle because only half of the arc will be on the left side and the other half on the right side.

    So considering I have progress of 25%

    sweepAngle = 90 degrees (90 degrees is quarter of a circle)
    start angle = 225 (45 degrees away from 270)
    

    If you want the progress to go from other sides (Left to right, right to left etc..) you will only need to replace 270 with the starting the angle.

    0 讨论(0)
  • 2020-11-28 04:48

    Finally I got the solution from this code:

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

    To calculate startAngle, use this code:

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

    Here, point1 means where you want to start drawing the Arc. sweepAngle means the angle between two lines. We have to calculate that by using two points like the blue points in my Question image.

    0 讨论(0)
  • 2020-11-28 04:56

    A simple solution was suggested here by Langkiller. This draws a cubic line from the start point via the control point to the end point.

    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)
    
    0 讨论(0)
  • 2020-11-28 04:57

    Do something like this:

    //Initialized paint on a class level object.
    Paint p = new Paint();
    p.setColor(Color.BLACK);
    //Calculate the rect / bounds of oval
    RectF rectF = new RectF(50, 20, 100, 80);
    
    @Override
    protected void onDraw(Canvas canvas) {      
        //Do the drawing in onDraw() method of View.
        canvas.drawArc (rectF, 90, 45, false, p);
    }
    
    0 讨论(0)
  • 2020-11-28 04:57

    first we need to visual how the coordinates are in terms of start and sweep angels then it will become more clear.

    so if you wanted just the right top piece of the circle, we could do something like this:

     val rect = RectF(0f, 0f, 500f, 300f)
            val paint = Paint()
            paint.apply {
                strokeWidth = 5f
                setStyle(Paint.Style.STROKE)
                color = COLOR.BLUE
            }
             path.addArc(rect, 270f, 90f)
    

    ..

    this starts at 270 (per the diagram above and 'sweeps` 90 degrees forward. you then have this shape:

    let's create one more so you get the hang of it. this time let's use a negative value: we want to create a semi half moon (arc) starting from the right side:

        path.addArc(rect, 0f, -180f)
    

    here we started at 0 and 'sweeped` -180 degrees. and the results are:

    0 讨论(0)
  • 2020-11-28 05:01

    a sample for draw arc.

    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 讨论(0)
提交回复
热议问题