克隆Fabric.js中的对象

时间:2014-02-10 08:18:14

标签: html5-canvas fabricjs

我使用一个简单的函数在Fabric.js中的画布上克隆选定的对象。

function duplicateObj() {
  var obj = canvas.getActiveObject();
  var clone = fabric.util.object.clone(obj);
  clone.set({left: 100,top: 100});
  canvas.add(clone); 
}

这绝对没问题。现在,如果我使用该对象并且不再需要克隆并且我选择并删除它,则删除对象,克隆和原始对象。删除功能是:

function deleteObj() {
  var obj = canvas.getActiveObject();
  canvas.fxRemove(obj);
}

对象是一样的。是否有方法克隆对象并使克隆独立于原始对象?我试过这个:

function duplicateObj() {
  var obj = canvas.getActiveObject();
  var clone = fabric.util.object.clone(obj);
  clone.initialize();
  $.extend(clone, obj);
  fabric.util.object.extend(clone, obj);
  clone.set({left: 100,top: 100});
  canvas.add(clone); 
}

它有效,但是对象再次相同,如果我只使用初始化,我最终会得到一个现在已设置属性的对象。

8 个答案:

答案 0 :(得分:12)

这是解决方案

 var object = fabric.util.object.clone(canvas.getActiveObject());
    object.set("top", object.top+5);
    object.set("left", object.left+5);
     canvas.add(object);

答案 1 :(得分:3)

我遇到了类似的问题,克隆上的操作会影响原始对象。我选择序列化对象并将其反序列化为一个新对象:

var copyData = canvas.getActiveObject().toObject();
fabric.util.enlivenObjects([copyData], function(objects) {
  objects.forEach(function(o) {
    o.set('top', o.top + 15);
    o.set('left', o.left + 15);
    canvas.add(o);
  });
  canvas.renderAll();
});

答案 2 :(得分:1)

for fabricjs 2.0

    $(".copy").on("click", function () {
                    var activeObject = canvas.getActiveObject();
                    activeObject.clone(function (cloned) {
                        canvas.discardActiveObject();
                        cloned.set({
                            top: cloned.top + 20,
                            evented: true
                        });
                        if (cloned.type === 'activeSelection') {
                            // active selection needs a reference to the canvas.
                            cloned.canvas = canvas;
                            cloned.forEachObject(function (obj) {
                                canvas.add(obj);
                            });
                            cloned.setCoords();
                        } else {
                            canvas.add(cloned);
                        }
                        canvas.setActiveObject(cloned);
                        canvas.requestRenderAll();
                    });
    });

答案 3 :(得分:0)

您可以使用

var obj = canvas.getActiveObject();
obj.clone(function(c) {
   canvas.add(c.set({ left: 100, top: 100, angle: -15 }));
});

在这里你可以看到它的工作原理: http://fabricjs.com/opacity_mouse_move/

答案 4 :(得分:0)

这是克隆选定对象或组的实现。

https://jsfiddle.net/milanhlinak/rxtjm7w0/1/

<!DOCTYPE html>
<html>

<head>
    <script type="text/javascript" src="lib/jquery-3.1.1.min.js"></script>
    <script type="text/javascript" src="lib/fabric.min.js"></script>
</head>

<body>

    <button onclick="cloneSelected()">Clone selected</button>
    <canvas id="canvas" style="border: 1px solid #cccccc"></canvas>

    <script>
        var canvas = new fabric.Canvas('canvas', {
            width: 500,
            height: 500,
        });

        canvas.add(new fabric.Rect({
            left: 100,
            top: 100,
            width: 50,
            height: 50,
            fill: '#faa'

        }));
        canvas.add(new fabric.Circle({
            left: 300,
            top: 300,
            radius: 25,
            fill: '#afa'
        }));


        function cloneSelected() {
            console.log('cloneSelected');

            var activeObject = canvas.getActiveObject();
            var activeGroup = canvas.getActiveGroup();

            if (activeObject) {
                console.log('object selected');

                var clonedObject = null;
                var json = activeObject.toJSON();
                if (json.type == 'rect') {
                    clonedObject = new fabric.Rect(json);
                } else if (json.type == 'circle') {
                    clonedObject = new fabric.Circle(json);
                } else {
                    console.log('unknown object type: ' + json.type);
                    return;
                }

                var oldLeft = clonedObject.getLeft();
                var oldTop = clonedObject.getTop();

                clonedObject.setLeft(oldLeft + 10);
                clonedObject.setTop(oldTop + 10);

                var boundingRect = clonedObject.getBoundingRect(true);
                if (boundingRect.left + boundingRect.width > canvas.getWidth()) {
                    clonedObject.setLeft(oldLeft);
                }
                if (boundingRect.top + boundingRect.height > canvas.getHeight()) {
                    clonedObject.setTop(oldTop);
                }

                canvas.add(clonedObject);
                canvas.setActiveObject(clonedObject);
                canvas.renderAll();
                console.log('selected object cloned');

            } else if (activeGroup) {
                console.log('group selected');

                canvas.discardActiveGroup();

                var clonedObjects = [];

                activeGroup.getObjects().forEach(function (object) {

                    var clonedObject = null;

                    var json = object.toJSON();
                    if (json.type == 'rect') {
                        clonedObject = new fabric.Rect(json);
                    } else if (json.type === 'circle') {
                        clonedObject = new fabric.Circle(json);
                    } else {
                        console.log('unknown object type: ' + json.type);
                        return;
                    }

                    clonedObject.setCoords();
                    canvas.add(clonedObject);
                    clonedObject.set('active', true);
                    clonedObjects.push(clonedObject);
                });

                var group = new fabric.Group(clonedObjects.reverse(), {
                    canvas: canvas
                });

                group.addWithUpdate(null);

                var oldLeft = group.getLeft();
                var oldTop = group.getTop();

                group.setLeft(oldLeft + 10);
                group.setTop(oldTop + 10);

                var boundingRect = group.getBoundingRect(true);
                if (boundingRect.left + boundingRect.width > canvas.getWidth()) {
                    group.setLeft(oldLeft);
                }
                if (boundingRect.top + boundingRect.height > canvas.getHeight()) {
                    group.setTop(oldTop);
                }

                group.setCoords();
                canvas.setActiveGroup(group);
                group.saveCoords();
                canvas.renderAll();
                console.log('selected objects cloned');
            } else {
                console.log('no object selected');
            }

        }
    </script>

</body>

</html>

答案 5 :(得分:0)

这对我来说效果很好,并且克隆的对象与原始对象完全没有链接:

var object = canvas.getActiveObject();

object.clone(function(clone) {
    canvas.add(clone.set({
        left: object.left + 10, 
        top: object.top + 10
    }));
});

您可以执行克隆所有选定对象的操作:

var activeObjects = canvas.getActiveObjects();

if (activeObjects) {
    activeObjects.forEach(function(object) {

        object.clone(function(clone) {
            canvas.add(clone.set({
                left: object.left + 10, 
                top: object.top + 10
            }));
        })

    });
}

希望它能对您有所帮助!

答案 6 :(得分:0)

我希望克隆能够将项目重置为最初保存的状态...像其他对象一样,我发现对象将变量传递给克隆,反之亦然...

我所做的是创建一个var来保存克隆,以便以后像这样调用:

var o; 
var object = canvas.getActiveObject().clone(
    function(obj){
        o = obj;
    }
);

一个警告,如果您设置了id并且在克隆过程中没有使它们唯一,那么它会使整个过程变得疯狂……除非您先删除原始ID。

答案 7 :(得分:-1)

在此处查看演示的复制和粘贴: http://fabricjs.com/copypaste

以下是复制/粘贴或克隆所选对象的代码。

function Clone() {
    Copy();
    Paste()
}

function Copy() {
    // clone what are you copying since you
    // may want copy and paste on different moment.
    // and you do not want the changes happened
    // later to reflect on the copy.
    canvas.getActiveObject().clone(function(cloned) {
        _clipboard = cloned;
    });
}

function Paste() {
    // clone again, so you can do multiple copies.
    _clipboard.clone(function(clonedObj) {
        canvas.discardActiveObject();
        clonedObj.set({
            left: clonedObj.left + 10,
            top: clonedObj.top + 10,
            evented: true,
        });
        if (clonedObj.type === 'activeSelection') {
            // active selection needs a reference to the canvas.
            clonedObj.canvas = canvas;
            clonedObj.forEachObject(function(obj) {
                canvas.add(obj);
            });
            // this should solve the unselectability
            clonedObj.setCoords();
        } else {
            canvas.add(clonedObj);
        }
        _clipboard.top += 10;
        _clipboard.left += 10;
        canvas.setActiveObject(clonedObj);
        canvas.requestRenderAll();
    });
}