moving line with circles on endpoints in fabric.js

4.1k views Asked by At

with fabric I'm trying to create a line with two circle endpoints. I can move the circles at the endpoints and the line updates. However if I move the line the circles don't move. Any suggestions?

JSFiddle here http://jsfiddle.net/gfk0r2pf/10/

var self = this;

var canvas = new fabric.Canvas('c', {
    selection: true
});

var line = new fabric.Line([50, 50, 100, 100], {
    fill: 'red',
    stroke: 'red',
    strokeWidth: 2,
    selectable: true,
    hasControls: false,
    hasBorders: false,
    centeredRotation: false,
    centeredScaling: false,
    //originX: 'center',
    //originY: 'center'
});

var circle1 = new fabric.Circle({
    radius: 5,
    fill: 'green',
    left: 45,
    top: 45,
    hasControls: false,
    hasBorders: false,
    name: 'circle1'
});

var circle2 = new fabric.Circle({
    radius: 5,
    fill: 'green',
    left: 95,
    top: 95,
    hasControls: false,
    hasBorders: false,
    name: 'circle2'
});

canvas.on('object:moving', function (options) {

    var objType = options.target.get('type');
    var p = options.target;

    if (objType == 'line') {        
        circle1.set({ x1: line.x1, y1: line.y1 });
        circle2.set({ left: line.x2, top: line.y2 });        
    } 
    if (objType == 'circle') {
        if (p.name == 'circle1') {
            line.set({
                x1: circle1.getCenterPoint().x, y1: circle1.getCenterPoint().y, selectable: true
            });
        } else {
            if (p.name == 'circle2') {
                line.set({
                    x2: circle2.getCenterPoint().x, y2: circle2.getCenterPoint().y, selectable: true
                });
            }
        }
    }
    line.setCoords();
    circle1.setCoords();
    circle2.setCoords();
    canvas.renderAll();

});

canvas.add(line);
canvas.add(circle1);
canvas.add(circle2);
 canvas.renderAll();
3

There are 3 answers

0
AhammadaliPK On

I had gone through your fiddle and fixed the problem , Please check it. Now it seems working.. check it this http://jsfiddle.net/Ahammadalipk/gfk0r2pf/14/

Change your code as below..

var self = this;

var canvas = new fabric.Canvas('c', {
    selection: true
});

var line = new fabric.Line([50, 50, 100, 100], {
    fill: 'red',
    stroke: 'red',
    strokeWidth: 2,
    selectable: true,
    hasControls: false,
    hasBorders: false,
    centeredRotation: false,
    centeredScaling: false,
    //originX: 'center',
    //originY: 'center'
});

var circle1 = new fabric.Circle({
    radius: 5,
    fill: 'green',
    left: 45,
    top: 45,
    hasControls: false,
    hasBorders: false,
    name: 'circle1'
});

var circle2 = new fabric.Circle({
    radius: 5,
    fill: 'green',
    left: 95,
    top: 95,
    hasControls: false,
    hasBorders: false,
    name: 'circle2'
});

canvas.on('object:moving', function (options) {

    var objType = options.target.get('type');
    var p = options.target;

    if (objType == 'line') {  
                    var _l = line.left;
                    var _t = line.top;

                    circle1.set({
                        'left': (line.calcLinePoints().x1 + _l),
                        'top': (line.calcLinePoints().y1 + _t)
                    });

                    circle1.line.set({
                        'x1': circle1.left,
                        'y1': circle1.top
                    });

                    circle1.line.setCoords();

                    circle2.set({
                        'left': (line.calcLinePoints().x2 + _l),
                        'top': (line.calcLinePoints().y2 + _t)
                    });

                    circle2.line.set({
                        'x2': circle2.left,
                        'y2': circle2.top
                    });

                    circle2.line.setCoords();
                    canvas.renderAll();

    } 
    if (objType == 'circle') {
        if (p.name == 'circle1') {
            line.set({
                x1: circle1.getCenterPoint().x, y1: circle1.getCenterPoint().y, selectable: true
            });
        } else {
            if (p.name == 'circle2') {
                line.set({
                    x2: circle2.getCenterPoint().x, y2: circle2.getCenterPoint().y, selectable: true
                });
            }
        }
    }
    line.setCoords();
    circle1.setCoords();
    circle2.setCoords();
    canvas.renderAll();

});

canvas.add(line);
circle1.line=line;
circle2.line=line;
canvas.add(circle1);
canvas.add(circle2);
 canvas.renderAll();
0
Dinesh Patil On

We can calculate the line drag distance and add that distance value in circles current value/

Please see fiddle: https://jsfiddle.net/LordWolfer/2pf0Lm81/99/

    var self = this;
    
    var canvas = new fabric.Canvas('c', {
      selection: true
    });
    
    var line = new fabric.Line([50, 50, 100, 100], {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 2,
      selectable: true,
      hasControls: false,
      hasBorders: false,
      centeredRotation: false,
      centeredScaling: false,
      perPixelTargetFind: true,
    });
    
    var circle1 = new fabric.Circle({
      radius: 5,
      fill: 'green',
      left: 45,
      top: 45,
      hasControls: false,
      hasBorders: false,
      name: 'circle1'
    });
    
    var circle2 = new fabric.Circle({
      radius: 5,
      fill: 'green',
      left: 95,
      top: 95,
      hasControls: false,
      hasBorders: false,
      name: 'circle2'
    });
    
    let diffX = 0,
      diffY = 0,
      circle1Left = circle1.left,
      circle1Top = circle1.top,
      circle2Left = circle2.left,
      circle2Top = circle2.top;
    canvas.on('object:moving', function(options) {
    
      var objType = options.target.get('type');
      var p = options.target;
      var t = options.transform;
    
      if (objType == 'line') {
    
        var _l = options.pointer.x;
        var _t = options.pointer.y;
    
        diffX = (options.pointer.x - t.ex);
        diffY = (options.pointer.y - t.ey);
        
        circle1.set({
          'left': (circle1Left + diffX),
          'top': (circle1Top + diffY)
        });
    
        circle1.line.set({
          'x1': circle1.left +5,
          'y1': circle1.top +5
        });
    
        circle1.line.setCoords();
    
        circle2.set({
          'left': (circle2Left + diffX),
          'top': (circle2Top + diffY)
        });
    
        circle2.line.set({
          'x2': circle2.left + 5,
          'y2': circle2.top +5
        });
        
        circle2.line.setCoords();
        canvas.renderAll();
    
      }
      else if (objType == 'circle') {
        if (p.name == 'circle1') {
          line.set({
            x1: circle1.getCenterPoint().x,
            y1: circle1.getCenterPoint().y,
            selectable: true
          });
        } else {
          if (p.name == 'circle2') {
            line.set({
              x2: circle2.getCenterPoint().x,
              y2: circle2.getCenterPoint().y,
              selectable: true
            });
          }
        }
        
        circle1Left = circle1.left,
        circle1Top = circle1.top,
        circle2Left = circle2.left,
        circle2Top = circle2.top;
      }
      line.setCoords();
      circle1.setCoords();
      circle2.setCoords();
      canvas.renderAll();
    
    });
    
    canvas.add(line);
    circle1.line = line;
    circle2.line = line;
    canvas.add(circle1);
    canvas.add(circle2);
    canvas.renderAll();

0
vitticeps On

You make the calculation based on the initial position of the circles/line. Need to calculate each of their positions at each scenario.

Please see fiddle: https://jsfiddle.net/251a9pog

I changed the colour of circle1 to blue to see the different in position of the 2 circles.

var self = this;

var canvas = new fabric.Canvas('c', {
    selection: true
});

var line = new fabric.Line([50, 50, 100, 100], {
    fill: 'red',
    stroke: 'red',
    strokeWidth: 2,
    selectable: true,
    hasControls: false,
    hasBorders: false,
    centeredRotation: false,
    centeredScaling: false
});

var circle1 = new fabric.Circle({
    radius: 5,
    fill: 'blue',
    left: 45,
    top: 45,
    hasControls: false,
    hasBorders: false,
    name: 'circle1'
});

var circle2 = new fabric.Circle({
    radius: 5,
    fill: 'green',
    left: 95,
    top: 95,
    hasControls: false,
    hasBorders: false,
    name: 'circle2'
});

canvas.on('object:moving', function (options) {

  var objType = options.target.get('type');
  var p = options.target;

  if (objType == 'line') {
     var c1Left, c1Top, c2Left, c2Top;
     // CALCULATE THE circle1 AND circle2 POINTS FOR EACH SCENARIO
     if (circle1.top < circle2.top) {
        if (circle1.left < circle2.left) {
           c1Left = p.left - circle1.radius;
           c1Top = p.top - circle1.radius;
           c2Left = p.left + p.width - circle2.radius;
           c2Top = p.top + p.height - circle2.radius;
        }
        else {
           c1Left = p.left + p.width - circle1.radius;
           c1Top = p.top - circle1.radius;
           c2Left = p.left - circle1.radius;
           c2Top = p.top + p.height - circle1.radius;
        }
     }
     else {
        if (circle1.left < circle2.left) {
           c1Left = p.left - circle1.radius;
           c1Top = p.top + p.height - circle1.radius;
           c2Left = p.left + p.width - circle1.radius;
           c2Top = p.top - circle1.radius;
        }
        else {
           c1Left = p.left + p.width - circle1.radius;
           c1Top = p.top + p.height - circle1.radius;
           c2Left = p.left - circle1.radius;
           c2Top = p.top - circle1.radius;
        }
     }
     circle1.set({ left: c1Left, top: c1Top });
     circle2.set({ left: c2Left, top: c2Top });
  }
  if (objType == 'circle') {
     if (p.name == 'circle1') {
        line.set({
           // moving circle left + radius
           x1: p.left + p.radius,
           // moving circle top + radius
           y1: p.top + p.radius,
           // other circle left + radius
           x2: circle2.left + circle2.radius,
           // other circle top + radius
           y2: circle2.top + circle2.radius,
           selectable: true
        });
     } else if (p.name == 'circle2') {
        line.set({
           // moving circle left + radius
           x1: p.left + p.radius,
           // moving circle top + radius
           y1: p.top + p.radius,
           // other circle left + radius
           x2: circle1.left + circle1.radius,
            // other circle top + radius
           y2: circle1.top + circle1.radius,
           selectable: true
        });
     }
  }
  line.setCoords();
  circle1.setCoords();
  circle2.setCoords();
  canvas.renderAll();
});

canvas.add(line);
canvas.add(circle1);
canvas.add(circle2);
canvas.renderAll();