Search code examples
javascripthtmlcanvasgeometric-arc

In Javascript canvas drawing, how do you eliminate the line in arc()?


I'm trying to draw an arc on a canvas in Javascript, but I want to get rid of the line that Javascript automatically draws. With the line being drawn, there are two problems: a) fill() malfunctions b) It looks like a bow

Here's an image of what I have and what I want: Arcs The left is what I have in JS, the right is what I have in Java. The Java implementation is fairly inefficient and I would like to use the functions already available.

Here are the relevant JS functions:

function pointAt(center, l, theta){
    return {
        x : Math.sin(theta) * l + center.x,
        y : Math.cos(theta) * l + center.y
    };
}

function drawArc(ctx, center, l, theta, sweep, label, thickness){
    var p0 = pointAt(center, l, theta);
    var p1 = pointAt(center, l + thickness, theta);
    var p2 = pointAt(center, l + thickness, theta + sweep);
    var p3 = pointAt(center, l, theta + sweep);
    ctx.fillStyle = "red";
    drawPoint(ctx, p0);
    ctx.fillStyle = "blue";
    drawPoint(ctx, p1);
    ctx.fillStyle = "green";
    drawPoint(ctx, p2);
    ctx.fillStyle = "yellow";
    drawPoint(ctx, p3);

    ctx.beginPath();
    ctx.moveTo(p0.x, p0.y);
    ctx.lineTo(p1.x, p1.y);
    ctx.arc(center.x, center.y, l + thickness, theta, theta + sweep, false);
    ctx.moveTo(p2.x, p2.y);
    ctx.lineTo(p3.x, p3.y);
    ctx.arc(center.x, center.y, l, theta + sweep, theta, true)
    ctx.closePath();
    ctx.fill();
    ctx.stroke();

    //TODO: draw label!!!
}

function drawPoint(ctx, p){
    ctx.fillRect(p.x - 4, p.y - 4, 8, 8);
}

Here's a working implementation in Java:

       private static void drawArc(Graphics g, Point center, int l, double theta, double sweep, String label, int thickness){
        for (double i = 0; i < thickness; i+=.5) { //hardcoded
            Point last = pointAt(center, l + i, theta);
            for(double t = theta; t < theta + sweep; t+=.01){
                Point cur = pointAt(center, l + i, t);
                g.drawLine(last.x, last.y, cur.x, cur.y);
                last = cur;
            }
        }
        double t = theta + sweep / 2;
        Point p = pointAt(center, l + 15, t);
        int size = g.getFontMetrics().stringWidth(label);
        BufferedImage img = new BufferedImage(size * 2, size * 2, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();
        g2.setColor(Color.RED);
        double rot = (Math.PI / 2 - t);
//      System.out.println(rot / Math.PI + "PI");
        boolean b = true;
        if(rot < -Math.PI / 2){
            rot += Math.PI;
            b = false;
        }
        g2.setTransform(AffineTransform.getRotateInstance(rot, size, size));
        g2.drawString(label, size, size);
        g2.dispose();
        if(!b)
            size *= 1.75; //magic value or hardcoded???
        g.drawImage(img, p.x - size, p.y - size, null);
    }

So my question: How do I turn the banana into a thick arc?


Solution

  • Just do:

    function drawArc(ctx, center, l, theta, sweep, label, thickness){
        var p0 = pointAt(center, l, theta);
        var p1 = pointAt(center, l + thickness, theta);
        var p2 = pointAt(center, l + thickness, theta + sweep);
        var p3 = pointAt(center, l, theta + sweep);
        ctx.fillStyle = "red";
        drawPoint(ctx, p0);
        ctx.fillStyle = "blue";
        drawPoint(ctx, p1);
        ctx.fillStyle = "green";
        drawPoint(ctx, p2);
        ctx.fillStyle = "yellow";
        drawPoint(ctx, p3);
    
        ctx.beginPath();
        //ctx.moveTo(p0.x, p0.y);
        //ctx.lineTo(p1.x, p1.y);
        ctx.arc(center.x, center.y, l + thickness, theta, theta + sweep, false);
        //ctx.moveTo(p2.x, p2.y);
        //ctx.lineTo(p3.x, p3.y);
        ctx.arc(center.x, center.y, l, theta + sweep, theta, true);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
    
        //TODO: draw label!!!
    }
    

    The "lateral" lines are implict placed, see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc.