Соедините два объекта с помощью 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


}


Мне было интересно, возможно ли это и как начать. Прошу совета.
719   2  

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

    Ничего не найдено.