javascript - FabricJS - 选择多个对象时将对象克隆到另一个 Canvas 会出错

标签 javascript html5-canvas grouping fabricjs

我有两个 Canvas 层,彼此堆叠。顶层名为top,底层名为bottom。在顶层上,我添加了一些透明的对象,并且只显示它们的句柄。 bottom 层应该克隆来自top的对象,更改一些属性并绘制它们。

只要我只移动顶层上的单个对象,这种方法就可以正常工作。当我选择一组对象并开始移动整个组时,出现了一些问题。在top层上一切正常,但bottom层上的对象被绘制到 Canvas 的左上角。仅当我开始再次拖动单个对象时,此问题才会得到纠正。

我希望有人可以看一下并可能知道出了什么问题:)


jsFiddle

var top = new fabric.Canvas("top", {renderOnAddRemove:false});
var bottom = new fabric.Canvas("bottom", {renderOnAddRemove:false});

var update = function () {  
  bottom.clear().add.apply(bottom, top.getObjects().map(function (o) {
    return o.clone().set({
      selectable: false,
      hasBorders: false,
      hasControls: false,
      fill: "rgba(255,0,0,.5)",
      globalCompositeOperation: "xor"
    });
  })).renderAll();
};

top.on({
  "object:modified": update
});

最佳答案

结构中的组很棘手,因为所有变换('top'、'left'、'scaleX'、'scaleY')都相对于父组的位置,而父组的位置都相对于组的中心。因此,当您想要提取顶级 Canvas 位置时,您需要做一些工作来从组中获取变换并将其应用到对象。在结构内部,当您对内容进行分组和取消分组时,就会发生这种情况。

在此示例中,我使所有对象具有与组的默认原点(中心)相同的 X 和 Y 原点。这使得矩阵计算匹配。如果您想保留形状的默认顶部/左侧原点,则需要进行额外的数学计算来计算正确的位置。

var topCanvas = new fabric.Canvas("top", {renderOnAddRemove:false});
var bottomCanvas = new fabric.Canvas("bottom", {renderOnAddRemove:false});

fabric.Object.prototype.originX = 'center';
fabric.Object.prototype.originY = 'center';

var update = function () {  
  bottomCanvas.clear().add.apply(bottomCanvas, topCanvas.getObjects().map(function (o) {
    var clone = o.clone();
    clone.set({
      selectable: false,
      hasBorders: false,
      hasControls: false,
      fill: "rgba(255,0,0,.5)",
      globalCompositeOperation: "xor",
    });

    if (o.group) {
      var matrix = o.calcTransformMatrix();
      var transforms = fabric.util.qrDecompose(matrix);
      clone.set({
        angle: transforms.angle,
        skewX: transforms.skewX,
        skewY: transforms.skewY,
        scaleX: transforms.scaleX,
        scaleY: transforms.scaleY,
        top: transforms.translateY,
        left: transforms.translateX,
      });
    }
    return clone;
  })).renderAll();
};

topCanvas.on({
  "object:modified": update
});

topCanvas
  .add(new fabric.Rect({
    top: 50,
    left: 50,
    width: 100,
    height: 100,
    fill: "transparent"
  }))
  .add(new fabric.Rect({
    top: 100,
    left: 100,
    width: 100,
    height: 100,
    fill: "transparent"
  }))
  .add(new fabric.Rect({
    top: 150,
    left: 150,
    width: 100,
    height: 100,
    fill: "transparent"
  }))
  .renderAll();

update();
#cont {
  position: relative;
  width: 400px;
  height: 300px;
  border: 1px solid;
}

canvas, .canvas-container {
  position: absolute!important;
  left: 0!important;
  top: 0!important;
  width: 100%!important;
  height: 100%!important;
}
<div id="cont">
  <canvas id="bottom" width="400" height="300"></canvas>
  <canvas id="top" width="400" height="300"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.min.js"></script>

关于javascript - FabricJS - 选择多个对象时将对象克隆到另一个 Canvas 会出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39119913/

相关文章:

R 条件分组行和组编号

sql - 如何在没有临时表的SQL查询中为组添加序列号

javascript - 在js对象中获取相同的订单数据

jquery - 为特定的 div 设置 L_PREFER_CANVAS = true

javascript - 将值插入数组而不填充(Javascript)

javascript - 在 Canvas 上移动对象

jquery - 使用 JQuery 将图像 "Upload"转换为 Canvas 对象 - 未保存在服务器上

python - 通过动态键名对字典进行分组并聚合Python中嵌套字典的一些键

javascript - 使用class和document.documentElement检测js

javascript - 创建具有设置约束的网格