fabricjs.com stickman: move the lines and affect the related circles

。_饼干妹妹 提交于 2020-01-25 11:18:06

问题


using the stickman example of http://fabricjs.com/, 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 & with errors :), as I can not to move the the related circles symmetrically.

If in the //move the other circle part is used next line

obj.set({ 'left': (s.calcLinePoints().x1 + _l), 'top': (-s.calcLinePoints().y1 + _t) });

  • the difference is in the sign of collected information for y1 and we move some horizontal line visually the result OK, but in my opinion this type of "adjustment" is not the correct one...

[example code]

$(function() {
  //create the fabriccanvas object & 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 && p.line1.set({
        'x2': p.left,
        'y2': p.top
      });
      p.line2 && 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 < 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 < 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 && currentObj.line1.set({
                'x2': currentObj.left,
                'y2': currentObj.top
              });
              currentObj.line2 && 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" && 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 && obj.line1.set({
                    'x2': obj.left,
                    'y2': obj.top
                  });
                  obj.line2 && obj.line2.set({
                    'x1': obj.left,
                    'y1': obj.top
                  });

                  obj.line2.setCoords();
                  obj.line1.setCoords();
                  //canvas.renderAll();
                }
              });
              canvas.renderAll();
              //end move oter
            }
          }

        }
      }

    }
  });

});
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>

Here it is the code on jsfiddle, too: https://jsfiddle.net/muybien/mzsa3z9L/

I want previously to thank you, even only for reading the question.


回答1:


Thanks of MiltoxBeyond's suggestion, the problem is fixed. Here it is a working and little cleaned example:

//to save the old cursor position: used on line mooving
var _curX, _curY;
$(function() {
  //create the fabriccanvas object & 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) {

    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;

    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), makeCircle(line.get('x2'), line.get('y2'), line, line2), makeCircle(line2.get('x2'), line2.get('y2'), line2, line3), makeCircle(line3.get('x2'), line3.get('y2'), line3, line4)
  );

  canvas.on('object:selected', function(e) {
    //find the selected object type
    var objType = e.target.get('type');
    if (objType == 'line') {
      _curX = e.e.clientX;
      _curY = e.e.clientY;
      //console.log(_curX);
      //console.log(_curY);
    }
  });

  canvas.on('object:moving', function(e) {
    //find the moving object type
    var p = e.target;
    var objType = p.get('type');

    if (objType == 'circle') {
      p.line1 && p.line1.set({
        'x2': p.left,
        'y2': p.top
      });
      p.line2 && 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') {
      var _curXm = (_curX - e.e.clientX);
      var _curYm = (_curY - e.e.clientY);
      //console.log("moved: " + _curXm);
      //console.log("moved: " + _curYm);

      //loop all circles and if some contains the line - move it
      for (var i = 0; i < canvas.getObjects('circle').length; i++) {
        var currentObj = canvas.getObjects('circle')[i];

        if (currentObj.line1.get("name") == p.get('name') || currentObj.line2.get("name") == p.get('name')) {

          currentObj.set({
            'left': (currentObj.left - _curXm),
            'top': (currentObj.top - _curYm)
          });

          currentObj.setCoords();

          currentObj.line1 && currentObj.line1.set({
            'x2': currentObj.left,
            'y2': currentObj.top
          });
          currentObj.line2 && currentObj.line2.set({
            'x1': currentObj.left,
            'y1': currentObj.top
          });

          currentObj.line2.setCoords();
          currentObj.line1.setCoords();
        }
      }
      _curX = e.e.clientX;
      _curY = e.e.clientY;
    }
  });

});
canvas {
  border: 1px solid #808080;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>


来源:https://stackoverflow.com/questions/30580744/fabricjs-com-stickman-move-the-lines-and-affect-the-related-circles

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!