Как нарисовать соединительные линии между фигурами, перетаскивая мышь в FabricJS - PullRequest
0 голосов
/ 03 мая 2018

Я пытаюсь построить блок-схему типа конечного автомата, используя Fabric js. Пока я могу динамически добавлять фигуры и просто рисовать линии между фиксированными точками. Я застрял при рисовании соединительных линий между фигурами, перетаскивая мышь из одного компонента в другой. Реально ли это с помощью FabricJS? если да, каковы подходы?

Кто-нибудь может пролить свет на это?

Вот что у меня есть,

import {
  Component
} from '@angular/core';
import 'fabric';

declare
let fabric;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';

  private canvas;
  private boundBox;
  private shape;

  ngOnInit() {

    // https://jsfiddle.net/ka7nhvbq/2/
    // http://jsfiddle.net/xvcyzh9p/45/

    this.canvas = new fabric.Canvas('canvas', {

    })

    this.shape = new fabric.Rect({
      width: 200,
      height: 200,
      top: 300,
      left: 200,
      fill: 'red',
      hasControls: false
    })

    this.canvas.add(this.shape)
    this.canvas.centerObject(this.boundBox)
  }

  getRandomColor() {
    var letters = '0123456789ABCDEF';
    var color = '#';
    for (var i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
  }



  addGambit() {
    let shape = new fabric.Rect({
      width: 200,
      height: 200,
      fill: this.getRandomColor(),
      hasControls: false
    })
    this.canvas.add(shape)
  }
  // By Simon Sarris

  addChildLine(options) {
    this.canvas.off('object:selected', this.addChildLine);

    // add the line
    var fromObject = this.canvas.addChild.start;
    var toObject = options.target;
    var from = fromObject.getCenterPoint();
    var to = toObject.getCenterPoint();
    var line = new fabric.Line([from.x, from.y, to.x, to.y], {
      fill: 'red',
      stroke: 'red',
      strokeWidth: 5,
      selectable: false
    });
    this.canvas.add(line);
    // so that the line is behind the connected shapes
    line.sendToBack();

    // add a reference to the line to each object
    fromObject.addChild = {
      // this retains the existing arrays (if there were any)
      from: (fromObject.addChild && fromObject.addChild.from) || [],
      to: (fromObject.addChild && fromObject.addChild.to)
    }
    fromObject.addChild.from.push(line);
    toObject.addChild = {
      from: (toObject.addChild && toObject.addChild.from),
      to: (toObject.addChild && toObject.addChild.to) || []
    }
    toObject.addChild.to.push(line);

    // to remove line references when the line gets removed
    line.addChildRemove = function() {
      fromObject.addChild.from.forEach(function(e, i, arr) {
        if (e === line)
          arr.splice(i, 1);
      });
      toObject.addChild.to.forEach(function(e, i, arr) {
        if (e === line)
          arr.splice(i, 1);
      });
    }

    // undefined instead of delete since we are anyway going to do this many times
    this.canvas.addChild = undefined;
  }

  addChildMoveLine(event) {
    this.canvas.on(event, function(options) {
      var object = options.target;
      var objectCenter = object.getCenterPoint();
      // udpate lines (if any)
      if (object.addChild) {
        if (object.addChild.from)
          object.addChild.from.forEach(function(line) {
            line.set({
              'x1': objectCenter.x,
              'y1': objectCenter.y
            });
          })
        if (object.addChild.to)
          object.addChild.to.forEach(function(line) {
            line.set({
              'x2': objectCenter.x,
              'y2': objectCenter.y
            });
          })
      }

      this.canvas.renderAll();
    });
  }

  addChild() {
    this.canvas.addChild = {
      start: this.canvas.getActiveObject()
    }

    // for when addChild is clicked twice
    this.canvas.off('object:selected', this.addChildLine);
    this.canvas.on('object:selected', this.addChildLine);
  }

}
<canvas width="800" height="800" id="canvas" class="canvas" style="border: 1px solid #666"></canvas>
<button (click)="addGambit()">add gambit</button>
...