2

我正在尝试用 Javascript 在画布上绘制弧线,但我想摆脱 Javascript 自动绘制的线条。随着线的绘制,有两个问题:a)fill()故障b)它看起来像一个弓

这是我拥有和想要的图像:弧线 左边是我在 JS 中拥有的东西,右边是我在 Java 中拥有的东西。Java 实现效率相当低,我想使用已经可用的功能。

以下是相关的JS函数:

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

这是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);
    }

所以我的问题是:如何将香蕉变成粗弧?

4

3 回答 3

3

顺时针画外弧,逆时针画内弧。画布将自动用直线为您关闭末端。

var c = document.getElementById('c');
var ctx = c.getContext('2d');
ctx.beginPath();
ctx.arc(0,0,50,0,-Math.PI * 0.5, false);
ctx.arc(0,0,25,-Math.PI * 0.5,0, true);
ctx.fillStyle = '#0f0';
ctx.fill();
ctx.strokeStyle = '#0f0';
ctx.stroke();
ctx.closePath();

http://jsfiddle.net/tMEdq/

此外,这里有很好的参考: http ://diveintohtml5.ep.io/canvas.html#divingin http://www.nihilogic.dk/labs/canvas_sheet/HTML5_Canvas_Cheat_Sheet.png

于 2011-06-29T18:59:19.997 回答
2

你也有太多的绘图调用——这就是你所需要的:

ctx.beginPath();
ctx.arc(center.x, center.y, l + thickness, theta, theta + sweep, false);
ctx.arc(center.x, center.y, l, theta + sweep, theta, true);
ctx.closePath();
ctx.fill();
ctx.stroke();

只需绘制第一条弧线,它会自动连接到下一条弧线,然后关闭路径以完成循环。

你也有你的sincos调用错误的方式pointAt()-sin()应该改变 Y 轴坐标,而不是 X 轴!

在http://jsfiddle.net/alnitak/zChSe/工作演示

于 2011-06-29T19:03:42.313 回答
1

做就是了:

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!!!
}

“横向”线是隐含的,请参阅http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc

于 2011-06-29T18:57:48.493 回答