使用Bezier或椭圆路径以编程方式绘制椭圆的一部分—;SVG和raphael.js

使用Bezier或椭圆路径以编程方式绘制椭圆的一部分—;SVG和raphael.js,svg,raphael,bezier,ellipse,elliptic-curve,Svg,Raphael,Bezier,Ellipse,Elliptic Curve,我正试图画一条贝塞尔曲线,它围绕一个给定边界的椭圆: 我希望通过编程实现这一点,因此如果我更改椭圆大小,曲线将跟随它 目前,我已经完成了以下功能: function bezierPathTopRounded(ellipse, margin) { var box = ellipse.paper.getBBox(); var leftX = box.x - margin; var rightX = box.x + margin + box.width; va

我正试图画一条贝塞尔曲线,它围绕一个给定边界的椭圆:

我希望通过编程实现这一点,因此如果我更改椭圆大小,曲线将跟随它

目前,我已经完成了以下功能:

function bezierPathTopRounded(ellipse, margin) {
    var box = ellipse.paper.getBBox();

    var leftX = box.x - margin; 

    var rightX = box.x + margin + box.width;

    var y = box.y + box.height/2 - margin; 

    var p = "M "+ leftX  + ", "+ y
    + " C " //could be relative too
    + ( box.x - margin + (box.width/15)  )  + ", " + ( box.y + margin - (box.height/4.5)  ) + " "
    + ( box.x + margin + box.width - (box.width/15)  )  + ", " + ( box.y + margin - (box.height/4.5) ) + " "
    + rightX +", " + y;

    return p;   
}
function borderPath(ellipse, flag) {
    var flag = flag == undefined ? 1 : flag;

    var box = ellipse.paper.getBBox();

    var leftX = box.x;

    var rightX = box.x + box.width;

    var y = box.y + box.height/2;

    var rx = box.width/2;
    var ry = box.height/2;

    var p = "M "+ leftX + ", "+ y
    + " A "
    + rx + " " + ry
    + " 0 0 "+ flag +" "
    + rightX +", " + y;

    return p;
}
但我不知道如何计算这个方向点的值,这样它就可以处理任何椭圆:

  • 方框宽度/15
  • 框高/4.5
有一个问题

我读过这篇文章,并在我的例子中尝试了同样的方法,但仍然无法找到一个简单的解决方案,它仍然是随机的

编辑

现在我尝试使用椭圆
A
rc,结果比使用贝塞尔路径更糟糕:

这就是我正在使用的函数。如果我去掉边距,它正好跟在我的椭圆后面。。。最后的问题是,我怎样才能沿着椭圆画一个边距

function borderPath(ellipse, margin, flag) {
    var flag = flag == undefined ? 1 : 0;

    var box = ellipse.paper.getBBox();

    var leftX = box.x - margin;

    var rightX = box.x + margin + box.width;

    var y = box.y + box.height/2;
    y += (flag == 1) ? -margin : margin;

    var rx = box.width/2 + margin;
    var ry = box.height/2;

    var p = "M "+ leftX + ", "+ y
    + " A "
    + rx + " " + ry
    + " 0 0 "+ flag +" "
    + rightX +", " + y;

    return p;
}


对于这些糟糕的颜色,我真的很抱歉,这些只是一个例子。

如果你想用贝塞尔曲线来做这件事,你必须决定你希望它看起来有多“错误”。贝塞尔曲线不能表示圆形(也可以说是椭圆形)曲线,它们只能非常接近,就像多边形一样,只需使用较少的截面就可以获得更高的精度

我在《Bezier曲线入门》中分别介绍了使用Bezier曲线的圆近似和曲线偏移,但如果您从头开始编写此代码,特别是如果您只需要将其用于示例中描述的内容,那么偏移将是多余的


相反,我建议启动Inkscape或Illustrator,打开网格覆盖,并围绕椭圆绘制贝塞尔曲线。让它看起来很好,然后检查坐标是什么,并将其用作在画布程序中实现的足够可靠的信息。你可能不需要数学上严格的正确,只要人们不去“那看起来是错误的”,你应该没事。

使用贝塞尔曲线绘制椭圆路径可能会让你头疼。正如您在评论中所说,您使用的是路径弧,它与RaphaelJS配合得很好


关于它期望的所有值的文档,特别是标志,可以在上找到。

我已经根据椭圆及其边距制作了椭圆弧。 而我只是用一个矩形来隐藏我不想要的部分

以下是函数:

function bezierPathTopRounded(ellipse, margin) {
    var box = ellipse.paper.getBBox();

    var leftX = box.x - margin; 

    var rightX = box.x + margin + box.width;

    var y = box.y + box.height/2 - margin; 

    var p = "M "+ leftX  + ", "+ y
    + " C " //could be relative too
    + ( box.x - margin + (box.width/15)  )  + ", " + ( box.y + margin - (box.height/4.5)  ) + " "
    + ( box.x + margin + box.width - (box.width/15)  )  + ", " + ( box.y + margin - (box.height/4.5) ) + " "
    + rightX +", " + y;

    return p;   
}
function borderPath(ellipse, flag) {
    var flag = flag == undefined ? 1 : flag;

    var box = ellipse.paper.getBBox();

    var leftX = box.x;

    var rightX = box.x + box.width;

    var y = box.y + box.height/2;

    var rx = box.width/2;
    var ry = box.height/2;

    var p = "M "+ leftX + ", "+ y
    + " A "
    + rx + " " + ry
    + " 0 0 "+ flag +" "
    + rightX +", " + y;

    return p;
}

为什么是贝塞尔?为什么不画另一个大小/位置合适的部分椭圆?你会遇到一个椭圆弧吗?我以前试过这个,但不可能,因为它的边缘不再是一个完美的椭圆。我需要它是一条路径,这样我才能画出这条特定的线。是的,我指的是一条椭圆弧,尽管我看到你的观点,同心椭圆可能不会产生你想要的效果。话虽如此,我认为贝塞尔曲线将永远只是一个近似值。您是如何推导出
box.width/15
box.height/4.5
?这不是一个推广数学的问题吗?在这两个数字都用到之前,我试了很多。这可能是一个推广数学的问题,不知道。。。我会用椭圆弧再试一次,让你知道。我已经用椭圆弧更新了,但是结果仍然是错误的…你得到了很好的文章!我同意他们不可能完全正确这一事实,但就我的例子来说,这看起来并没有那么“错误”,不是吗?我不能用Inkscape等制作它们,因为我想根据椭圆设置它们的动画。到目前为止,我的解决方案是为路径使用两个不同的函数(开始、结束)。现在,如果我想要“完美”曲线,我应该使用椭圆弧吗这也不正确,因为它是由边缘切割的,使用椭圆弧可能对你来说已经足够好了,只要你用相同的量偏移两个半径。因此,如果椭圆是(x,y,r1,r2),并且希望偏移量超过椭圆的一半,比如说10px,那么可以使用圆弧(x,y,r1+10,r2+10,pi,2*pi),最后两个表示圆弧的起点和终点角度。这里的问题是,如果您使用的是Canvas2D,目前唯一可用的圆弧就是圆弧。椭圆弧命令(“椭圆”)最终出现在更新草案中(我是请求它的人之一,很高兴现在添加了它),但不受支持。yetI使用Raphael(svg无画布,因此
A
Arx-axis-rotation大弧旗扫掠旗xy)但我会尝试用这些信息找到一种方法,谢谢。这里似乎需要的是在椭圆周围的等宽边缘的外缘画一条细线。如果是这样,那么边距可以计算为法线到椭圆的恒定投影轨迹-。我怀疑这样的轨迹是椭圆;对于任何偏心率的椭圆,随着边距宽度的增加,它将趋向于一个圆。如果你能使它工作,那么结果应该是好的,但要编写方程、计算投影和绘制轨迹,需要做大量的工作。由于方程是笛卡尔坐标,而不是极坐标,您可能需要分别处理椭圆的上/下和左/右弧,否则迭代增量将趋于无穷小。