将HTML5 Canvas.arc移植到Android和逆时针

时间:2013-08-22 14:51:40

标签: android drawing android-canvas

我正在将Skycons移植到Android上,我的大部分都在工作,除了月亮使用带有逆时针参数的HTML5 Canvas.arc

我试图这样实现:

RectF rect = new RectF();

public void arcR( Path path, float x, float y, float radius, double startAngle, double endAngle, boolean anticlockwise ){
    // Set bounds
    rect.set( x - radius, y - radius, x + radius, y + radius );

    // Convert to degrees
    startAngle = Math.toDegrees(startAngle);
    endAngle = Math.toDegrees(endAngle);

    if(anticlockwise){
        startAngle = 360 - startAngle;
        endAngle = 360 - endAngle;
    }

    endAngle = endAngle - startAngle;

    path.addArc(rect, (float)startAngle, (float)endAngle);
}

我认为我没有正确实施逆时针,因为在我的设备上绘制月球(基于Skycons)看起来像这样:

Screenshot

4 个答案:

答案 0 :(得分:5)

对于逆时针弧,扫掠角需要为负

float sweepAngle = ((endAngle + 360) - startAngle) % 360;
if (anticlockwise) {
  sweepAngle = sweepAngle - 360;
}
path.addArc(rect, startAngle, sweepAngle);

答案 1 :(得分:0)

double sweepAngle = endAngle - startAngle;
startAngle = 360 - endAngle;
path.addArc(rect, (float)startAngle, (float)sweepAngle);

答案 2 :(得分:0)

要绘制一条剪切线,您需要找到第二个圆的中心。我假设切口圆半径与原始圆相同,但当然你可以改变它。

请尝试以下代码:

private void drawMoon(Path path, float x, float y, float radius, float startAngle, float endAngle) {

  float sweepAngle = endAngle - startAngle;

  float x1 = (float) (x + radius * Math.cos(Math.toRadians(startAngle)));
  float y1 = (float) (y + radius * Math.sin(Math.toRadians(startAngle)));

  float x2 = (float) (x + radius * Math.cos(Math.toRadians(endAngle)));
  float y2 = (float) (y + radius * Math.sin(Math.toRadians(endAngle)));

  float x3 = (x1 + x2) / 2;
  float y3 = (y1 + y2) / 2;
  float q = (float) Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));

  float r = radius; // cutout circle radius
  float cx = (float) (x3 + Math.sqrt(r * r - (q / 2) * (q / 2)) * (y1 - y2) / q);
  float cy = (float) (y3 + Math.sqrt(r * r - (q / 2) * (q / 2)) * (x2 - x1) / q);

  path.rewind();

  rect.set(x - radius, y - radius, x + radius, y + radius);
  path.addArc(rect, startAngle, sweepAngle);

  rect.set(cx - r, cy - r, cx + r, cy + r);
  path.addArc(rect, (float) Math.toDegrees(Math.atan2(y1 - cy, x1 - cx)), 360 - sweepAngle);

}

答案 3 :(得分:0)

html5 canvas arc和android canvas arc之间的区别:

  1. 在html5 / javascript中你将centerX,centerY,radius作为前3个参数。在android中,你给出了围绕圆圈而不是那些3的矩形。这对圆圈来说有点麻烦,但更灵活,因为你也可以做椭圆(椭圆)

  2. 在javascript中,您将逆时针的起始角度,结束角度和布尔值作为参数4,5,6。在android中,你给出了起始角度和“扫掠角度”。 “扫掠角”是端角和起始角之间的差。如果你想要逆时针,只需给出负扫描角度。

  3. javascript角度是弧度,在android中它们是度数。

  4. 作为一个例子,这里有一些示例代码,它绘制一个C形图形,左边是一个长弧,右边是3个短弧,其中一个是逆时针。

    JavaScript的:

    <!DOCTYPE HTML>
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html" />
            <title>arcs</title>
            <script type="text/javascript">
    function initPage(){
        ctx = document.getElementById("canvas").getContext('2d');
        ctx.fillStyle = "blue";
        pi = Math.PI;
        r = 100;
        R = 3 * r;
        padding = 5;
        width = 2 * (R + padding);
        height = width;
        centerX = padding + width/2;
        centerY = padding + height/2;
        ctx.beginPath();
        ctx.arc(centerX, centerY,       R,   pi/2, 3*pi/2, false);
        ctx.arc(centerX, centerY - 2*r, r, 3*pi/2,   pi/2, false);
        ctx.arc(centerX, centerY,       r, 3*pi/2,   pi/2, true );
        ctx.arc(centerX, centerY + 2*r, r, 3*pi/2,   pi/2, false);
        ctx.fill();
    }
            </script>        
        </head>
    
        <body onload="initPage();">
            <canvas id="canvas" width="610" height="610"></canvas>
        </body>
    </html>
    

    机器人:

    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.RectF;
    import android.graphics.drawable.BitmapDrawable;
    import android.os.Bundle;
    import android.widget.ImageView;
    
    public class MainActivity extends Activity {
    
        private void drawToImageView(ImageView iv){
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.BLUE);
            Path path = new Path();
            int radius = 140;
            int Radius = 3 * radius;
            int padding = 5;
            int width = 2 * (Radius + padding);
            int height = width;
            Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bm);
            float a = 90f;
            float b = 3*a;
            float pi = 2*a;
            float _radius = (float)radius;
            float _Radius = (float)Radius;
            float centerX = padding + width/2;
            float centerY = padding + height/2;
            path.addArc(circRect(centerX, centerY,             _Radius), a,  pi);
            path.addArc(circRect(centerX, centerY - 2*_radius, _radius), b,  pi);
            path.addArc(circRect(centerX, centerY,             _radius), b, -pi);
            path.addArc(circRect(centerX, centerY + 2*_radius, _radius), b,  pi);
            canvas.drawPath(path, paint);
            iv.setImageDrawable(new BitmapDrawable(getResources(), bm));
        }
        private RectF circRect(float centerX, float centerY, float radius){
            float left   = centerX - radius;
            float right  = centerX + radius;
            float top    = centerY - radius;
            float bottom = centerY + radius;
            return new RectF(left, top, right, bottom);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ImageView iv = (ImageView)findViewById(R.id.myImageView);
            drawToImageView(iv);
        }
    }