问题
I'm trying to build a state machine kind of flow diagram using Fabric js. So far I'm able to dynamically add shapes and just draw lines between fixed points. I'm stuck at drawing connector lines between shapes by dragging the mouse from one component to another. Is it really possible using FabricJS? if yes, what are the approaches?
Can anyone throw some light on this?
Here is what I have so far,
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>
来源:https://stackoverflow.com/questions/50148390/how-to-draw-connector-lines-between-shapes-by-dragging-mouse-in-fabricjs