【问题标题】:Cloning objects in Fabric.js在 Fabric.js 中克隆对象
【发布时间】:2014-03-07 11:27:44
【问题描述】:

我正在使用一个简单的函数在 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); 
}

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

【问题讨论】:

  • 您应该在对象本身上使用clone 方法。每个对象都有它,它会照顾一切
  • 谢谢。我克隆了一个组。这就是问题所在。克隆单个对象可以正常工作。
  • 嗨@Benick!您找到克隆组的解决方案了吗?

标签: html5-canvas fabricjs


【解决方案1】:

解决办法

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

【讨论】:

【解决方案2】:

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

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();
});

【讨论】:

  • 这是从画布复制到另一个画布时将原件和副本相互分离的唯一解决方案。
  • 这似乎不起作用,可能是对 fabric 的更新。
【解决方案3】:

对于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();
                    });
    });

【讨论】:

    【解决方案4】:

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

    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
                }));
            })
    
        });
    }
    

    希望对你有帮助!

    【讨论】:

      【解决方案5】:

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

      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>
      

      【讨论】:

        【解决方案6】:

        你可以使用

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

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

        【讨论】:

          【解决方案7】:

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

          我所做的是创建一个 var 来保存克隆以供以后调用,如下所示:

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

          需要注意的是,如果您设置了 id 并且在克隆过程中没有使它们独一无二,这会使整个事情变得疯狂...除非您先删除原始 ID..

          【讨论】:

            【解决方案8】:

            在此处查看复制和粘贴的演示: 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();
                });
            }
            

            【讨论】:

              猜你喜欢
              • 2014-03-04
              • 2018-06-23
              • 2011-02-04
              • 2010-09-18
              • 2020-11-04
              • 2011-07-18
              • 2011-06-30
              • 1970-01-01
              相关资源
              最近更新 更多