【问题标题】:Connect two objects using fabric js使用fabric js连接两个对象
【发布时间】:2015-09-01 19:46:34
【问题描述】:

我目前有一个画布应用程序,可以在其中添加对象(形状)。这是我的FIDDLE。您基本上单击将初始化画布的新模拟,然后您可以添加一个圆形或矩形。

我正在尝试添加一个名为“添加子项”的功能,您可以在其中单击某个对象(形状),然后单击添加子项并添加另一个对象(形状),它们都与一条线链接。类似于 DEMO 的东西。

我认为此功能的伪代码如下所示:

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


}

我想知道这是否可能以及如何开始。请指教。

【问题讨论】:

    标签: javascript canvas fabricjs


    【解决方案1】:

    你需要监听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;
    }
    

    window.addChild 跟踪是否单击了 Add Child(并且应该添加到按钮的 onclick 中),以便下一个 object:selected 可以画线(否则它只会跟踪当前选择的元素)

    <button onClick="addChild()">Add Child</button>
    

    请注意,要获得完整的解决方案,您需要能够取消添加子项,并且您可能想要处理对象大小调整(当前,当您移动对象时行会更新,但在调整对象大小时不会更新)


    小提琴 - http://jsfiddle.net/ctcdaxop/

    【讨论】:

    • 这太棒了,为了取消添加孩子,我想我应该简单地删除活动对象吗?例如我在一个子对象上选择它被认为是活动对象,我应该简单地删除它吗?
    • 只需将canvas.connect 设置为false。
    • jsfiddle.net/6zqbq7rp 这就是我所做的,但由于某种原因我无法删除连接线。我什至尝试将 canvas.connect 设置为 false。再次感谢您的帮助
    • 嗯好的,需要存储对line对象的引用,添加删除方法,删除对象时调用。您还需要在移动处理程序中处理缺失的行。试一试,或者我可以在几个小时后摆弄它。
    • 确定没问题,谢谢,当我尝试分离将两个对象连接到新函数的代码时,我也会尽力做到这一点,但出现了一些问题。原因是我严格尝试保留它以创建新画布的 newAnimation 函数。因此,如果您确实收到一封机会信,也请告诉我是否可能。再次感谢您的精彩贡献。
    【解决方案2】:

    这是您正在寻找的新版本,包括对多个连接和删除的支持

    添加子功能

    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/

    【讨论】:

    • 我应该把这个作为一个单独的问题发布,这样你就可以在那里回答了吗?我确实赞成,我觉得它应该得到更多的回报。
    • 没问题,保持原样 - 点赞就足够了。干杯!
    • 嘿,我刚刚发布了一个新问题,也许你可以帮助stackoverflow.com/questions/32670825/…
    • 嗨,我想知道你是否有机会看看我的问题:)。我正在阅读 Fabric JS 动画教程@fabricjs.com/animation-easing
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多