Canvas.drawArc() artefacts

前端 未结 2 1373
伪装坚强ぢ
伪装坚强ぢ 2021-02-04 16:47

I draw an arc on canvas in a custom view as shown below. Paint and rectangle are defined outside of onDraw() and added in there for simpli

相关标签:
2条回答
  • 2021-02-04 17:26

    I've found the solution! :)

    Instead of this:

    RectF rectangle = new RectF(60f, 60f, 480f, 480f);
    
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(0x40000000);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(120);
    
    canvas.drawArc(rectangle, 225f, 315f, false, paint);
    

    Use this:

    RectF rectangle = new RectF(60f, 60f, 480f, 480f);
    
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(0x40000000);
    paint.setStyle(Paint.Style.FILL);
    
    float strokeWidth = 120;
    float startAngle = 225f;
    float sweepAngle = 315f;
    
    RectF pathRect = new RectF();
    Path path = new Path();
    float s = strokeWidth / 2;
    pathRect.left = rectangle.left - s;
    pathRect.right = rectangle.right + s;
    pathRect.top = rectangle.top - s;
    pathRect.bottom = rectangle.bottom + s;
    path.arcTo(pathRect, startAngle, sweepAngle);
    pathRect.left = rectangle.left + s;
    pathRect.right = rectangle.right - s;
    pathRect.top = rectangle.top + s;
    pathRect.bottom = rectangle.bottom - s;
    path.arcTo(pathRect, startAngle + sweepAngle, -sweepAngle);
    path.close();
    canvas.drawPath(path, paint);
    

    This code results in slower run, but it doesn't produce artefacts. :)

    0 讨论(0)
  • 2021-02-04 17:33

    I'm a StackOverflow newbie, wanted to add a comment but could not (having insufficient points) so had to put my comment in an answer !

    One strange thing is that the arc overshoots the specified end position with a straight vertical line at the outer side. The inner end point seems to be ok. Of course this and the other mess of lines does not tell what causes the problem.

    It seems to appear when the end angle is at exactly a multiple of 90 degrees. This looks like a numeric calculation bug, float round-off issue etc. @kcoppock remarked that 314.98f already circumvents the bug. Probably any value other than exactly 315.0f may do the trick.

    If code optimization is involved (attempts to draw the arc in as little line segments as possible) another trick that may work is to simplify the arc by cutting it into pieces -> use multiple drawArc calls that each span a certain maximum angle. Candidates are 30, 45, 90 and 180 degrees. Remains to be seen if the joints will be invisible...

    It's a bit of a long shot, hope any of these suggestions might work.

    0 讨论(0)
提交回复
热议问题