带有三个手柄的贝塞尔曲线错位了控制点

我设法用拉斐尔图书馆的例子绘制了四条不同的曲线。 现在,我想创建一个包含多个手柄的曲线。 如何在此示例中添加更多句柄。

    Bezier curve  #holder { height: 100%; left: 100%; margin: -100% 0 0 -100%; position: absolute; top: 100%; width: 100%; }     $('document').ready(function () { var r = Raphael("holder", window.innerWidth, window.innerHeight) function curve(x, y, ax, ay, bx, by, zx, zy, color) { var path = [["M", x, y], ["C", ax, ay, bx, by, zx, zy]], path2 = [["M", x, y], ["L", ax, ay], ["M", bx, by], ["L", zx, zy]], curve = r.path(path).attr({stroke: color || Raphael.getColor(), "stroke-width": 4, "stroke-linecap": "round"}), controls = r.set( r.path(path2).attr({stroke: "#ccc", "stroke-dasharray": ". ","stroke-width":2}), r.circle(x, y, 5).attr({fill: "#9F2200", stroke: "none"}), r.circle(ax, ay, 5).attr({fill: "#9F2200", stroke: "none"}), r.circle(bx, by, 5).attr({fill: "#9F2200", stroke: "none"}), r.circle(zx, zy, 5).attr({fill: "#9F2200", stroke: "none"}) ); controls[1].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[0][1] = X; path[0][2] = Y; path2[0][2] = X; path2[0][2] = Y; controls[2].update(x, y); }; controls[2].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[1][3] = X; path[1][2] = Y; path2[1][4] = X; path2[1][2] = Y; curve.attr({path: path}); controls[0].attr({path: path2}); }; controls[3].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[1][3] = X; path[1][4] = Y; path2[2][5] = X; path2[2][2] = Y; curve.attr({path: path}); controls[0].attr({path: path2}); }; controls[4].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[1][5] = X; path[1][6] = Y; path2[3][6] = X; path2[3][2] = Y; controls[3].update(x, y); }; controls.drag(move, up); } function move(dx, dy) { this.update(dx - (this.dx || 0), dy - (this.dy || 0)); console.log(this.dx,this.dy); this.dx = dx; this.dy = dy; } function up() { this.dx = this.dy = 0; } curve(70, 100, 110, 100, 130, 200, 170, 200, "hsb(0, 0, 0)"); curve(800, 200, 800, 100, 600, 100, 600, 200, "hsb(0, 0, 0)"); // xp1,yp1, , , , , xp2,yp2 where (xp1,xp2) & (xp2,yp2) are two end points curve(500, 200,500, 300, 300, 300, 300, 200, "hsb(0, 0, 0)"); // xp1,yp1, , , , , xp2,yp2 where (xp1,xp2) & (xp2,yp2) are two end points curve(920, 100,880, 100, 1020, 200, 980, 200, "hsb(0, 0, 0)"); });    

演示的链接是http://jsfiddle.net/insane36/fddGJ/1/

我编辑了代码并再次尝试放置多个句柄以显示中间的主句柄但有一些问题,我不知道我是否理解它背后的概念。 我想用下图创建一个带手柄的图形,并能够操纵手柄;

在此处输入图像描述

三个句柄的代码是;

     Bezier curve  #holder { height: 100%; left: 100%; margin: -100% 0 0 -100%; position: absolute; top: 100%; width: 100%; }    window.onload=function () { var r = Raphael("holder", window.innerWidth, window.innerHeight) function curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2,cx3,cy3,cx4,cy4, color) { //zx --x1 var path = [["M", x1, y1], ["C", cx1, cy1, cx2, cy2, x2, y2,"S",cx3,cy3,cx4,cy4]], path2 = [["M", x1, y1], ["L", cx1, cy1], ["M", cx2, cy2], ["L", x2, y2],["M", cx3,cy3],['L',cx4,cy4]], curve = r.path(path).attr({stroke: color || Raphael.getColor(), "stroke-width": 4, "stroke-linecap": "round"}), controls = r.set( r.path(path2).attr({stroke: "#ccc", "stroke-dasharray": ". ","stroke-width":2}), r.circle(x1, y1, 5).attr({fill: "#9F2200", stroke: "none"}), r.circle(cx1, cy1, 5).attr({fill: "#9F2200", stroke: "none"}), r.circle(cx2, cy2, 5).attr({fill: "#9F2200", stroke: "none"}), r.circle(x2, y2, 5).attr({fill: "#9F2200", stroke: "none"}), r.circle(cx3, cy3, 5).attr({fill: "#9F2200", stroke: "none"}), r.circle(cx4, cy4, 5).attr({fill: "#9F2200", stroke: "none"}) ); controls[1].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[0][9] = X; path[0][2] = Y; path2[0][10] = X; path2[0][2] = Y; controls[2].update(x, y); }; controls[2].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[1][11] = X; path[1][2] = Y; path2[1][12] = X; path2[1][2] = Y; curve.attr({path: path}); controls[0].attr({path: path2}); }; controls[3].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[1][3] = X; path[1][4] = Y; path2[2][13] = X; path2[2][2] = Y; curve.attr({path: path}); controls[0].attr({path: path2}); }; controls[4].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[1][5] = X; path[1][6] = Y; path2[3][14] = X; path2[3][2] = Y; controls[3].update(x, y); }; controls[5].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[1][8] = X; path[1][9] = Y; path2[4][15] = X; path2[4][2] = Y; controls[4].update(x, y); }; controls[6].update = function (x, y) { var X = this.attr("cx") + x, Y = this.attr("cy") + y; this.attr({cx: X, cy: Y}); path[1][10] = X; path[1][11] = Y; path2[5][16] = X; path2[5][2] = Y; controls[5].update(x, y); }; controls.drag(move, up); } function move(dx, dy) { this.update(dx - (this.dx || 0), dy - (this.dy || 0)); console.log(this.dx,this.dy); this.dx = dx; this.dy = dy; } function up() { this.dx = this.dy = 0; } curve(10, 80, 40, 10, 65,10,150,150,95, 80, 180,180, "hsb(0, 0, 0)"); };    

我想我已经错过了,没有正确安排控制点和值

看看这个小提琴 – 我想我已经做了你正在寻找的东西。 ( 编辑:修复这个小提琴,这样你就不必在curve()构造函数中指定reflection的控制点)

我认为关键是曲线中间点的第二个控制点只是第一个控制点的反映(根据SVG文档 ),所以你必须对那些控制的’假’进行排序。 (你的代码确实有一些问题,你的update()函数试图更新不存在的数组值,比如path[1][6] = Y; path[1]只有三个元素)

如果你希望两个控制点独立运行(这样曲线在这一点上不一定是平滑的),我认为你必须从你的路径中删除“S”,并改变一些代码(这里是一个像那个 )

如果您希望允许两个控制点从该点移动不同的距离,但保持曲线平滑点,我认为您必须手动执行此操作。 您可以从第二个示例开始,但是您必须以编程方式将移动控制点的角度反映到相对的控制点,同时允许从相对控制点到曲线上的点的距离保持固定。