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

标签 javascript fabricjs

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

这演示了我遇到的一些问题:

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 约束的错误。

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

任何关于我可以在这里改变什么的建议都会很棒。谢谢!

最佳答案

这是代码,您需要的,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>

关于javascript - 使用 PolyLines 通过 FabricJS 连接拖放形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55057419/

相关文章:

javascript - 如何将鼠标悬停事件更改为点击事件?

javascript - 从 Javascript 追加后,Textarea 不会使用预填充值自动增长高度

javascript - 如何在 Chrome 的 PDF 查看器中显示带有名称的 javascript 文件对象?

fabricjs - Fabricjs v2 之后 ClipTo 的替代品是什么?

fabricjs - Fabric Js 中具有自定义属性的自定义绘图工具

canvas - Fabric.js 中的 'toObject()' 函数

javascript - 使用 jquery 和 css 在点击时展开 div

Javascript 在此 JSON 中添加一个变量

javascript - 如何自动更新复制的 fabricjs Canvas ?

jquery - 用于富文本编辑的 Fabric.js javascript 框架