使用PolyLines通过FabricJS连接拖放形状

时间:2019-03-08 05:49:04

标签: javascript fabricjs

我想使用一条折线连接两个矩形,并在矩形移动时保持与各个矩形上相同点的连接(具体来说,对于页面上的两个矩形,我希望折线连接底部一个矩形的中间点到另一个矩形的顶部中间部分。我使用PolyLine的原因是,我最终还将在这条路的后面添加弯头)。我遇到了折线坐标更新以响应移动矩形的问题。

这表明了我遇到的一些问题:

var canvas = new fabric.Canvas('c');
rect = null;
line = null;

function addLine(x1, y1, x2, y2) {
  var coords = [{x: x1, y: y1}, {x: x2, y: y2}];
    
  this.line = new fabric.Polyline(coords, {
    stroke: 'green',
    strokeWidth: 5,
    fill: 'rgba(0,0,0,0)',
    selectable: true,
    evented: false
  });

  this.canvas.add(this.line);
}

function addRect(left, top, width, height, line1, line2, line3, line4) {
  this.rect = new fabric.Rect({
    left: left,
    top: top,
    width: width,
    height: height,
    fill: '#9f9',
    originX: 'left',
    originY: 'top',
    centeredRotation: true 
  });

  this.rect.line1 = line1;
  this.rect.line2 = line2;
  this.rect.line3 = line3;
  this.rect.line4 = line4;

  this.canvas.add(this.rect);
}

var r1_left = 10;
var r1_top = 20;
var r1_width = 125;
var r1_height = 150;
var r2_left = 350;
var r2_top = 300;
var r2_width = 125;
var r2_height = 150;

addLine(r1_left + r1_width/2, r1_top + r1_height, r2_left + r2_width/2, r2_top);
addRect(r1_left, r1_top, r1_width, r1_height, null, null, this.line, null);  
addRect(r2_left, r2_top, r2_width, r2_height, this.line, null, null, null);

this.canvas.renderAll();

this.canvas.on('object:moving', function(e) {
  var p = e.target;

  if (p.line1) {
    let x_2_new = p.left + p.width/2; 
    let y_2_new = p.top;
    p.line1.set('points', [p.line1.points[0], {'x': x_2_new, 'y': y_2_new}]);
    p.line1.set('height', y_2_new - p.line1.points[0]['y']);
    p.line1.set('width', x_2_new - p.line1.points[0]['x']);
    p.set('oCoords', p.line1.calcCoords());
  } else if (p.line2) {
    p.line2.set({'points': [{'x': p.left + p.width, 'y': p.top + p.height/2}, p.line2.points[1]]});
  } else if (p.line3) {
    p.line3.set({'points': [{'x': p.left + p.width/2, 'y': p.top + p.height}, p.line3.points[1]]});
  } else if (p.line4) {
    p.line4.set({'points': [p.line4.points[0], {'x': p.left, 'y': p.top + p.height/2}]});
  } 
});
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
  </head>
  <body>
    <canvas id="c" width="700" height="700" style="border:1px solid #ccc"></canvas>
    <script>
    </script>
  </body>
</html>

对于上方的矩形,我尝试在对象移动时简单地设置x和y坐标。这样,我遇到一个错误,即x和y似乎受直线的oCoords和aCoords约束。

对于下部矩形,我尝试直接设置坐标。这样,整行似乎都在页面上移动。

任何有关我可以在此处进行更改的建议都是很棒的。谢谢!

1 个答案:

答案 0 :(得分:1)

这是您需要的代码,jsfiddle

(function() {
  var canvas = this.__canvas = new fabric.Canvas('c', { selection: false });
  fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

  function makeCircle(left, top, line1, line2) {
    var c = new fabric.Rect({
      top: top,
      left: left,
      width: 30,
      height: 30,
      selection: false,
      fill: '#ccc'
      });
      c.hasControls = c.hasBorders = false;

      c.line1 = line1;
      c.line2 = line2;

      return c;
  }

  function makeLine(coords) {
    return new fabric.Line(coords, {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 5,
      selectable: false,
      evented: false,
    });
  }

  var line = makeLine([ 250, 125, 250, 375 ]),
      line2 = makeLine([ 250, 375, 250, 350 ]);

  canvas.add(line);

  canvas.add(
    makeCircle(line.get('x1'), line.get('y1'), null, line),
    makeCircle(line.get('x2'), line.get('y2'), line, line2),
  );

  canvas.on('object:moving', function(e) {
    var p = e.target;
    p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
    p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
    canvas.renderAll();
  });
})();
<div>
    <canvas id="c" width="700" height="575" style="border:1px solid #999"></canvas>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.min.js"></script>