Соедините два объекта с помощью fabric js
В настоящее время у меня есть приложение canvas, в котором я могу добавлять объекты(фигуры). Вот моя скрипка . Вы в основном нажимаете на новую симуляцию, которая инициализирует холст, затем вы можете добавить круг или прямоугольник.
Я пытаюсь добавить функцию под названием "добавить ребенка", где вы можете нажать на какой-то объект (фигуру), затем нажать Добавить ребенка и добавить другой объект(фигуру), и они оба связаны с линией. Что-то похожее на эту демонстрацию .
Я вычислил код песудо для эта функция будет выглядеть примерно так:
function addChild(){
get getActiveObject
draw a line/arrow connect it with getActiveObject
draw object connected with line
should be able to move it / strecth it around
}
Мне было интересно, возможно ли это и как начать. Прошу совета.
2 ответов:
Вам нужно прослушать событие
object:selected, чтобы добавить соединительную линию, и событиеobject:moving, чтобы обновить координаты линии.// function for drawing a line function makeLine(coords) { return new fabric.Line(coords, { fill: 'red', stroke: 'red', strokeWidth: 5, selectable: false }); } var canvas; window.newAnimation = function(){ canvas = new fabric.Canvas('canvas'); var selectedElement = null; canvas.on('object:selected', function(options) { // we are doing t oadd a connection if (canvas.connect) { canvas.connect = false; var from = selectedElement.getCenterPoint(); var to = options.target.getCenterPoint(); var line = makeLine([from.x, from.y, to.x, to.y]); canvas.add(line); // these take care of moving the line ends when the object moves selectedElement.moveLine = function() { var from = selectedElement.getCenterPoint(); line.set({ 'x1': from.x, 'y1': from.y }); }; options.target.moveLine = function() { var to = options.target.getCenterPoint(); line.set({ 'x2': to.x, 'y2': to.y }); }; } selectedElement = options.target; }); canvas.on('object:moving', function(e) { e.target.moveLine(); canvas.renderAll(); }); } window.addChild = function() { canvas.connect = true; }Окно.addChild отслеживает, был ли нажат Add Child (и должен быть добавлен в onclick для кнопки), чтобы следующий
object:selectedмог нарисовать линию (в противном случае он просто отслеживает текущий выбранный элемент)<button onClick="addChild()">Add Child</button>Обратите внимание, что для полного решения вам нужно иметь возможность отменить добавление дочернего элемента, и вы, вероятно, захотите это сделать. обрабатывать изменение размера объекта (в настоящее время строка обновляется при перемещении объекта, но не изменяется при изменении размера объекта)
Скрипка - http://jsfiddle.net/ctcdaxop/
Вот новая версия того, что вы ищете, включая поддержку нескольких соединений и удаление
Добавить Дочерние Функции
function addChildLine(options) { canvas.off('object:selected', addChildLine); // add the line var fromObject = 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 }); 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 canvas.addChild = undefined; } function addChildMoveLine(event) { 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 }); }) } canvas.renderAll(); }); } window.addChild = function () { canvas.addChild = { start: canvas.getActiveObject() } // for when addChild is clicked twice canvas.off('object:selected', addChildLine); canvas.on('object:selected', addChildLine); }Поскольку у нас нет ссылки на холст, если не щелкнуть добавить анимацию, обработчик должен быть прикреплен в обработчике добавить анимацию
window.newAnimation = function () { canvas = new fabric.Canvas('canvas'); // we need this here because this is when the canvas gets initialized ['object:moving', 'object:scaling'].forEach(addChildMoveLine) }
Удаление строк при удалении объектов
window.deleteObject = function () { var object = canvas.getActiveObject(); // remove lines (if any) if (object.addChild) { if (object.addChild.from) // step backwards since we are deleting for (var i = object.addChild.from.length - 1; i >= 0; i--) { var line = object.addChild.from[i]; line.addChildRemove(); line.remove(); } if (object.addChild.to) for (var i = object.addChild.to.length - 1; i >= 0; i--) { var line = object.addChild.to[i]; line.addChildRemove(); line.remove(); } } // from original code object.remove(); }
Скрипка - http://jsfiddle.net/xvcyzh9p/
Comments