title: fabricjs.com stickman: move the lines and affect the related circles
body: <p>using the <strong><em>stickman</em></strong> example of <a href="http://fabricjs.com/" rel="nofollow">http://fabricjs.com/</a>,
  I have been trying to achieve moving the related circles when a line is moved. The code in the example is not well structured, heavy &amp; with errors :), as I can not to move the the related circles symmetrically.</p>
  
  <p>If in the <strong>//move the other circle</strong> part is used next line</p>
  
  <blockquote>
    <p>obj.set({
          'left': (s.calcLinePoints().x1 + _l),
          'top': (<strong>-s.calcLinePoints().y1</strong> + _t)
        });</p>
  </blockquote>
  
  <ul>
  <li>the difference is in the sign of collected information for y1 <strong>and we move some horizontal line visually the result OK</strong>, but in my opinion this type of "adjustment" is not the correct one...</li>
  </ul>
  
  <p>[example code]</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>$(function() {
    //create the fabriccanvas object &amp; disable the canvas selection
    var canvas = new fabric.Canvas('c', {
      selection: false
    });
    //move the objects origin of transformation to the center
    fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
  
    function makeCircle(left, top, line1, line2, usedLine, usedEnd) {
      //used line - used line for the center
      //usedEnd - fromt the used line
  
      var c = new fabric.Circle({
        left: left,
        top: top,
        strokeWidth: 2,
        radius: 6,
        fill: '#fff',
        stroke: '#666'
      });
  
      c.hasControls = c.hasBorders = false;
  
      c.line1 = line1;
      c.line2 = line2;
  
      //add information which line end is used for center
      var _usedLineName;
  
      if (usedLine == 1) {
        _usedLineName = line1.name;
      } else {
        _usedLineName = line2.name;
      }
  
      c.usedLineName = _usedLineName;
      c.usedEndPoint = usedEnd;
  
      return c;
    }
  
    function makeLine(coords, name) {
      var l = new fabric.Line(coords, {
        stroke: 'red',
        strokeWidth: 4,
        selectable: true, //false
        name: name
      });
  
      l.hasControls = l.hasBorders = false;
  
      return l;
    }
  
    //initial shape information
    var line = makeLine([250, 125, 350, 125], "l1"),
      line2 = makeLine([350, 125, 350, 225], "l2"),
      line3 = makeLine([350, 225, 250, 225], "l3"),
      line4 = makeLine([250, 225, 250, 125], "l4");
  
    canvas.add(line, line2, line3, line4);
  
    canvas.add(
      makeCircle(line.get('x1'), line.get('y1'), line4, line, 1, 2),
      makeCircle(line.get('x2'), line.get('y2'), line, line2, 1, 2),
      makeCircle(line2.get('x2'), line2.get('y2'), line2, line3, 1, 2),
      makeCircle(line3.get('x2'), line3.get('y2'), line3, line4, 1, 2));
  
  
  
    canvas.on('object:moving', function(e) {
      //find the moving object type
      var objType = e.target.get('type');
      var p = e.target;
  
      if (objType == 'circle') {
        p.line1 &amp;&amp; p.line1.set({
          'x2': p.left,
          'y2': p.top
        });
        p.line2 &amp;&amp; p.line2.set({
          'x1': p.left,
          'y1': p.top
        });
        //set coordinates for the lines - should be done if element is moved programmely
        p.line2.setCoords();
        p.line1.setCoords();
  
        canvas.renderAll();
      } else if (objType == 'line') {
  
        //loop all circles and if some is with coordinates as some of the ends - to change them
        for (var i = 0; i &lt; canvas.getObjects('circle').length; i++) {
  
          var currentObj = canvas.getObjects('circle')[i];
  
          if (currentObj.get("usedLineName") == e.target.get('name')) {
  
            //usedEndPoint=2
            for (var ss = 0; ss &lt; canvas.getObjects('line').length; ss++) {
              var s = canvas.getObjects('line')[ss];
              //console.log(s.calcLinePoints())
              //console.log(s.calcLinePoints().y2)
              var _l = s.left;
              var _t = s.top;
              if (s.get("name") == currentObj.get("usedLineName")) {
                currentObj.set({
                  'left': (s.calcLinePoints().x2 + _l),
                  'top': (s.calcLinePoints().y2 + _t)
                });
                console.log(s.calcLinePoints().y2 + _t)
                currentObj.setCoords();
  
                currentObj.line1 &amp;&amp; currentObj.line1.set({
                  'x2': currentObj.left,
                  'y2': currentObj.top
                });
                currentObj.line2 &amp;&amp; currentObj.line2.set({
                  'x1': currentObj.left,
                  'y1': currentObj.top
                });
  
                currentObj.line2.setCoords();
                currentObj.line1.setCoords();
  
  
                //move the other circle
                canvas.forEachObject(function(obj) {
                  var _objType = obj.get('type');
                  if (_objType == "circle" &amp;&amp; obj.line2.name == s.get("name")) {
  
                    obj.set({
                      'left': (s.calcLinePoints().x1 + _l),
                      'top': (s.calcLinePoints().y1 + _t)
                    });
                    console.log(s.calcLinePoints().y1 + _t)
                    obj.setCoords();
  
                    obj.line1 &amp;&amp; obj.line1.set({
                      'x2': obj.left,
                      'y2': obj.top
                    });
                    obj.line2 &amp;&amp; obj.line2.set({
                      'x1': obj.left,
                      'y1': obj.top
                    });
  
                    obj.line2.setCoords();
                    obj.line1.setCoords();
                    //canvas.renderAll();
                  }
                });
                canvas.renderAll();
                //end move oter
              }
            }
  
          }
        }
  
      }
    });
  
  });</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;canvas id="c" width="500" height="500"&gt;&lt;/canvas&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Here it is the code on jsfiddle, too:
  <a href="https://jsfiddle.net/muybien/mzsa3z9L/" rel="nofollow">https://jsfiddle.net/muybien/mzsa3z9L/</a></p>
  
  <p>I want previously to thank you, even only for reading the question.</p>