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

时间:2013-04-19 08:03:34

标签: svg raphael bezier ellipse elliptic-curve

我正在尝试绘制一条围绕具有给定边距的椭圆的贝塞尔曲线:

Bezier path surrounding an ellipse

我想以编程方式实现此目的,因此如果我更改椭圆大小,曲线将遵循它。

目前我已经完成了这项功能:

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

但我无法弄清楚如何计算这个方向点值,以便它可以用于任何椭圆:

  • box.width / 15
  • box.height / 4.5

fiddle with this example

我已经阅读了这个stackoverflow question,我在我的例子中尝试过相同的内容,但仍然无法找到一个简单的解决方案,它仍然是随机的...

修改

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

Elliptical Arc test

我正在使用的功能。如果我删除了边距,那么它就是我的椭圆...最后,问题是我如何跟踪带有边距的椭圆?

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

请参阅updated fiddle here

对于糟糕的颜色真的很抱歉,这些都是出于好的目的。

3 个答案:

答案 0 :(得分:2)

如果你想用贝塞尔曲线做这个,你必须决定你想要它看起来有多“错误”。贝塞尔曲线不能表示圆形(和扩展的椭圆形)曲线,它们只能以多边形相同的方式变得非常接近,只需使用较少的截面就可以获得更高的精度。

我在Bezier曲线的引物中分别使用贝塞尔曲线描述了圆近似和曲线偏移,分别为http://pomax.github.io/bezierinfo/#circles_cubichttp://pomax.github.io/bezierinfo/#offsetting,但是如果你从头开始编码,特别是偏移将是过度的如果你只需要你在你的例子中描述的内容。

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

答案 1 :(得分:1)

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

这是功能:

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

答案 2 :(得分:0)

使用贝塞尔曲线绘制椭圆路径可能会让您头疼。正如您在评论中所说,您正在使用与RaphaelJS一起使用的路径弧。

可以在http://www.svgbasics.com/arcs.html找到有关其所需的所有值的文档,尤其是标志。