请问有人能解释一下arcTo的最后两个参数是什么意思吗?涉及到IT技术相关内容。

18

我正在尝试绘制一个带有圆角的矩形。我有一个能够完成这个任务的 JavaScript 路径,但是 JavaScript 的 arcTo 方法需要一个矩形(用来定义其椭圆形)和一个参数来设置扫描范围。

然而,在 Android 版本中有三个参数。第一个参数是矩形椭圆,我认为我已经正确地定义了它,接下来的两个参数分别是起始角度和扫描角度(我不理解使用方法)。但是,当我尝试根据自己的猜测进行调整时,我的弧线看起来与期望的完全不同。

有人知道一个好的教程吗?

具体来说,如果我想从12-3在钟表面上绘制一条弧线,并假设我有一条线从3延伸到底部,然后需要将角从3弯到6等等,那么这两个参数会是什么样子呢?

这是我的代码(现在忽略其中的弧线数字...这只是我猜测如何工作的最新迭代,之前更有意义的尝试失败了):

Path ctx = new Path();
        ctx.moveTo(X+5,Y); //A
        ctx.lineTo(X+W-5,Y);//B
        ctx.arcTo(new RectF(X+W, Y, X+W, Y+5), -180, 90); //B arc

        ctx.lineTo(X+W,Y+H-5); //C
        ctx.arcTo(new RectF(X+W,Y+H,X+W-5,Y+H),90,180); //C arc

        ctx.lineTo(X+W/2 +6,Y+H);
        ctx.lineTo(X+W/2,Y+H+8);
        ctx.lineTo(X+W/2-6,Y+H);
        ctx.lineTo(X+5,Y+H);
        ctx.arcTo(new RectF(X,Y+H,X,Y+H-5),180,270);

        ctx.lineTo(X,Y+5);
        ctx.arcTo(new RectF(X,Y,X+5,Y),270,0);
        Paint p = new Paint();
        p.setColor(0xffff00ff);

        canvas.drawPath(ctx, p);

非常感谢。

4个回答

31

有点奇怪没有人回答,但是一旦我找到答案(很难找),就变得非常简单了。

那么,它的工作方式如下: 假设你想在12-3的位置(使用时钟参考)绘制一个圆角: 你开始你的路径,当你需要弧线时,你定义一个矩形,其左上角是你当前线条结束的地方,并且其右下角是你希望弧线前往的地方,所以如果你想象一下一个正方形,其X,Y是12(在时钟上),而其X + W,Y + H是3,那么这就是你需要的正方形。

现在,想象一下你在那个正方形中有一个椭圆形(在本例中它是一个圆形的椭圆形,如果你想让你的曲线更像椭圆形,则将正方形定义为矩形),你可以使用方法的最后两个参数来取任何一个圆的切片。第一个参数定义你想要开始切割的角度。如果使用罗盘,0度是东方(不确定为什么,我不是几何学专家……这正常吗?我总是认为0是北方,但我看到的所有编程几何示例都把0作为东方,也许有人会评论为什么这样)。

第二个参数定义了你想要多少圆。如果你想要整个圆,你就把360放进去;如果你只想要半个圆,你就把180放进去,等等。

所以,在我们的例子中,由于我们想要从12到3的角落圆角,因此我们将270作为起始度数,并获得90度的圆。

最后,当你完成这个过程时,线条现在会认为它在下午3点的位置,所以你可以从那里继续线路(lineTo)。

所以……这是我的形状修正代码(它有一个小三角形,但那不重要,实际的圆弧部分是B-C,D-E,I-J和K-A。所有其他部分都是直线)。

int arc = 25;
    public Cursor(int X, int Y, int W, int H){
        /*
         *   A            B
         * K                C 
         * J                D
         *   I   H   F    E
                   G
         */
        int Ax = X+ arc;
        int Ay = Y;
        int Bx = X + W - arc;
        int By = Y;
        int Cx = X + W;
        int Cy = Y + arc;
        int Dx = Cx;
        int Dy = (Y + arc) + (H - arc*2);
        int Ex = Bx;
        int Ey = Y + H;
        int Fx = X+W/2 +6;
        int Fy = Ey;
        int Gx = X+W/2;
        int Gy = Y+H+8;
        int Hx = X+W/2-6;
        int Hy = Ey;
        int Ix = Ax;
        int Iy = Hy;
        int Jx = X;
        int Jy = Dy;
        int Kx = X;
        int Ky = Cy;


        Path ctx = new Path();
        ctx.moveTo(Ax,Ay); //A
        ctx.lineTo(Bx,By);//B
        ctx.arcTo(new RectF(Bx, By, Cx, Cy), 270, 90); //B-C arc

        ctx.lineTo(Dx,Dy); //D
        ctx.arcTo(new RectF(Dx - arc, Dy, Ex + arc, Ey),0,90); //D-E arc

        ctx.lineTo(Fx, Fy); //E-F
        ctx.lineTo(Gx, Gy); //F-G
        ctx.lineTo(Hx, Hy); //G-H
        ctx.lineTo(Ix, Iy); //H - I
        ctx.arcTo(new RectF(Jx, Jy, Ix, Iy),90,90);// I = J arc

        ctx.lineTo(Kx, Ky); //K
        ctx.arcTo(new RectF(Ax - arc, Ay, Kx + arc, Ky),180,90); //K - A arc
        ctx.lineTo(Ax, Ay); //K



        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setColor(0xffffffff);
        p.setStyle(Style.FILL);
        canvas.drawPath(ctx, p);    
        p.setColor(0xff000000);
        p.setStyle(Style.STROKE);
        p.setStrokeWidth(3);            
        canvas.drawPath(ctx, p);



    }

1
想象一下你的弧被一个矩形所包围(并且延伸到该矩形内部的所有位置,即使只有你想显示的部分会被显示出来)。第一个参数是你的椭圆内部起始点的度数,第二个参数是你想要抓取完整椭圆的度数,以成为你的弧段。 - Yevgeny Simkin
1
这确实有所帮助,但也在一个非常重要的方面误导了我。该方法不适用于一般情况,且不够精确。根据它们的坐标从12到3绘制弧形,需要定义一个外接时钟的矩形(不是以12为左上角/3为右下角),并指定起始角度为270和扫描角度为90。代码不会从B到C绘制弧线,而是从B开始绘制一条长度为矩形一半的直线,然后是一段弧线,最后再绘制一条长度为矩形一半的直线到C。如果B和C不是90度角,则无法绘制。尽管如此,这让我有了一个好的开端,所以谢谢! - Jayz7522
1
@GeniaS。当然,但也许您可以重新阅读一下我的上文,那里非常精确。最快的方法是编辑您的代码:选择一个角落,比如右上角,并用一些显眼的颜色绘制矩形。不要从270(在矩形上)开始弧线,而是从300开始,例如。您会注意到,弧线并不是从矩形的左上角开始的,而是从内切于矩形的圆的第300度开始的。您的回答暗示着如果从点A到B绘制弧线,则应选择具有左上角A,右下角B的矩形,但事实并非如此。 - Jayz7522
1
非常感谢@GeniaS的清晰解释。使用模拟时钟来解释角度使得一切都变得轻而易举。我只用不到4行代码就创建了一个披萨片路径对象。感谢您的洞察力。 - i_o
1
"0度是东方(不确定为什么...)- 将其视为正切,东部边缘的正切将是一条垂直线,因此为0度。" - hmac
显示剩余8条评论

8

这篇答案通过四个例子来直观解释了arcTo的所有参数。

arcTo接受以下参数:

public void arcTo(RectF oval, 
                  float startAngle, 
                  float sweepAngle, 
                  boolean forceMoveTo)

RectF的构造函数接受以下参数:

RectF(float left, float top, float right, float bottom)

可视化解释arcTo函数参数

(希望这个可视化解释比官方的arcTo文档更容易理解和 less painful。)


2
感谢这个例子,它使参数非常清晰易懂。根据我在Android开发文档中所读的,你可能可以省略一些“lineTo()”调用(除了指向点F、G、H的那些),因为arcTo会在绘制的第一个点不是圆弧的最后一个点时自动添加lineTo...
至于为什么0度从东边开始,这是因为数学和三角学课程通常假定0度标记是三角形圆(以0,0为圆心,半径为1)与X轴相交的点,即东方(然而,这些同样的课程通常逆时针计算角度,因此90度变成北方,270度是南方,而在Android上,角度似乎是顺时针计算的)。

0
这里是一些示例代码(从我的一个类中拼凑而来)用于绘制一个填充的、圆角矩形,然后添加一个描边矩形来给它加上边框:
//Initializing some stuff
_paint = new Paint();
_rect = new RectF();
_radius = 10;
_bgColor = 0xFFFFFFFF;
_borderColor = 0xFFCCCCCC;

//Doing dimension calculations
_rect.left = 0;
_rect.top = 0;
_rect.right = this.getWidth() - 1;
_rect.bottom = this.getHeight() - 1;

//painting
//draw the background
_paint.setColor(_bgColor);
_paint.setStyle(Style.FILL_AND_STROKE);
canvas.drawRoundRect(_rect, _radius, _radius, _paint);

//draw the border
_paint.setStrokeWidth(1);
_paint.setColor(_borderColor);
_paint.setStyle(Style.STROKE);
canvas.drawRoundRect(_rect, _radius, _radius, _paint);

我很感激,但这不是我想要的...我想了解arcTo方法。我的形状严格来说不是一个矩形,它底部有一个小箭头。 - Yevgeny Simkin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接