在Javascript画布绘图中,如何消除arc()中的线条?

发布于 2024-11-17 15:58:14 字数 2685 浏览 5 评论 0原文

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

这是我拥有的和我想要的图像: Arcs 左边是我在 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);
    }

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

遥远的绿洲 2024-11-24 15:58:14

只需顺时针绘制外圆弧,然后逆时针绘制内圆弧即可。画布会自动为您用直线封闭两端。

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

Just draw the outer arc clockwise, then the inner arc counter-clockwise. The canvas will automatically close off the ends with straight lines for you.

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/

Also, here are good references:
http://diveintohtml5.ep.io/canvas.html#divingin
http://www.nihilogic.dk/labs/canvas_sheet/HTML5_Canvas_Cheat_Sheet.png

没企图 2024-11-24 15:58:14

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

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

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

您还在 pointAt() 中以错误的方式调用了 sincos - sin() 应该改变Y 轴坐标,而不是 X 轴!

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

You have way too many drawing calls too - this is all you need:

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

Just draw the first arc, which will automatically get joined to the next, and then close the path to complete the loop.

You also have your sin and cos calls the wrong way around in pointAt() - sin() should alter the Y axis coordinate, not the X axis!

Working demo at http://jsfiddle.net/alnitak/zChSe/

兮子 2024-11-24 15:58:14

只要这样做:

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文