title: Bezier curve with three handles misplaces the control points
body: <p>I managed to draw four different curves with the examples of the Raphael library. Now, I would like to create a single curve with multiple handles in it. How do I add more handles in this example.</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
      &lt;head&gt;
          &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;
          &lt;title&gt;Bezier curve&lt;/title&gt;
              &lt;style&gt;
          #holder {
              height: 100%;
              left: 100%;
              margin: -100% 0 0 -100%;
              position: absolute;
              top: 100%;
              width: 100%;
          }
          &lt;/style&gt;
          &lt;script src='jquery.js'&gt;&lt;/script&gt;
          &lt;script src="raphael.js"&gt;&lt;/script&gt;
          &lt;script&gt;
             $('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) &amp; (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) &amp; (xp2,yp2) are two end points 
  
                      curve(920, 100,880, 100, 1020, 200, 980, 200, "hsb(0, 0, 0)"); 
  
              });
          &lt;/script&gt;
      &lt;/head&gt;
      &lt;body&gt;
          &lt;div id="holder"&gt;&lt;/div&gt;
      &lt;/body&gt;
  &lt;/html&gt;
  
  &lt;/body&gt;
  </code></pre>
  
  <p></p>
  
  <p>The link for demo is <a href="http://jsfiddle.net/insane36/fddGJ/1/" rel="nofollow noreferrer">http://jsfiddle.net/insane36/fddGJ/1/</a></p>
  
  <p>I edited the code and again tried to put multiple handle to show the main handle in the middle but has some problem and I dont know if I understood the concept behind it. I wanted to create a figure with handle as figure below and be able to manipulate the handles;</p>
  
  <p><img src="https://i.stack.imgur.com/EXSNo.png" alt="enter image description here"></p>
  
  <p>The code for three handles is ;</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
      &lt;head&gt;
          &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;
          &lt;title&gt;Bezier curve&lt;/title&gt;
              &lt;style&gt;
          #holder {
              height: 100%;
              left: 100%;
              margin: -100% 0 0 -100%;
              position: absolute;
              top: 100%;
              width: 100%;
          }
          &lt;/style&gt;
          &lt;script src="raphael.js"&gt;&lt;/script&gt;
          &lt;script&gt;
             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)");
  
              };
          &lt;/script&gt;
      &lt;/head&gt;
      &lt;body&gt;
          &lt;div id="holder"&gt;&lt;/div&gt;
      &lt;/body&gt;
  &lt;/html&gt;
  
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>I think I have missed and not arranged properly the control points and the values</p>