【问题标题】:How to get the canvas-relative position of an object that is in a group?如何获取组中对象的画布相对位置?
【发布时间】:2015-07-01 23:52:10
【问题描述】:

通常,对象相对于画布的位置可以从它的.left 和.top 属性中获得,但如果对象在选择/组中,则这些属性相对于组。有没有办法让他们相对于画布的位置?

【问题讨论】:

  • 这是您要找的吗? jsfiddle.net/uue3hcj6/3 正如你所说的它们相对于组,你可以使用组的左和上来找到画布上的绝对位置。
  • 这似乎不适用于选择:jsfiddle.net/uue3hcj6/4
  • 这一切都取决于为对象/组设置的原点。在第一个小提琴中,我将组原点设置为中心。这就是为什么我没有在计算中添加组宽度的 1/2(group.left 给了我它的中心到画布左侧的距离)。但默认情况下,原点设置为顶部/左侧。因此,对于选择(您的情况)或没有将原点设置为中心的组,group.left 是组左侧与画布左侧的距离。现在为什么我需要将组宽度的一半添加到计算中?这是因为 object.left 是从组中心到对象左侧的测量值。
  • 这可能解释得更好:组的原点设置为中心:i.imgur.com/csLtv7U.png 与组的原点设置为顶部/左侧(默认):i.imgur.com/PY0JJfo.png
  • @SwapnilJain 感谢您的解释!我现在明白了,我之前没有看到“originX”是什么意思。如果您将此作为答案并 ping 我,我会将您的答案标记为解决方案

标签: javascript fabricjs


【解决方案1】:

当一个对象在组内时,其相对于画布的坐标将取决于组的原点(以及对象的原点)。

假设我们有这个代码,它有一个矩形和一个圆形添加到一个组中。

var canvas = new fabric.Canvas(document.getElementById('c'));

var rect = new fabric.Rect({
    width: 100,
    height: 100,
    left: 50,
    top: 50,
    fill: 'rgba(255,0,0,0.5)'
});
var circle = new fabric.Circle({
    radius: 50,
    left: 175,
    top: 75,
    fill: '#aac'
});

var group = new fabric.Group([rect, circle],{
    originX: 'center',
    originY: 'center'
});
canvas.add(group);
canvas.renderAll();

以下是使组居中的三种可能情况:

  1. 组的原点设置为中心(如上面的代码):

    如下图所示,rect.left 给出了对象左侧到组中心的距离。 rect.group.left 给出了组中心到画布左侧的距离。

    所以矩形到画布左侧的距离 = rect.left + rect.group.left (http://jsfiddle.net/uue3hcj6/3/)

  2. 组的原点设置为顶部/左侧(也是默认设置)

    rect.left 给出了对象左侧到组中心的距离。 rect.group.left 为我们提供了组左侧与画布左侧的距离。现在要计算剩余距离,我们必须添加组的一半宽度。

    所以矩形到画布左侧的距离 = rect.left + rect.group.left + rect.group.width/2 (http://jsfiddle.net/uue3hcj6/6/)

  3. 组的原点设置为底部/右侧

    rect.left 给出了对象左侧到组中心的距离。 rect.group.left 为我们提供了组右侧与画布左侧的距离。现在要计算总距离,我们必须减去组宽度的一半。

    所以矩形到画布左侧的距离 = rect.left + rect.group.left - rect.group.width/2(http://jsfiddle.net/uue3hcj6/7/)

注意:对象也可能出现类似情况。

【讨论】:

  • 终于有人解释了fabricjs的所有“魔力”,谢谢。
  • 我还是不明白。例如,在您的第一个示例中,如果我们更改圆的左侧,并为组添加角度,则矩形的位置也会更改!我正在尝试修复组内的所有对象并围绕其中心旋转组本身,但由于某种原因,所有移动的对象都没有固定,我不知道为什么。
  • 那么嵌套组呢?......这是我们必须发明自己的自行车的罕见功能吗? :|
【解决方案2】:

作为对Swapnil Jain's answer 的补充,top 属性也是如此。

所以:

absoluteLeft = rect.left + rect.group.left - rect.group.width / 2
absoluteTop = rect.top + rect.group.top - rect.group.height / 2

【讨论】:

    【解决方案3】:

    解决方案是考虑组宽。 object.left 是相对于组的中心,而不是左侧,所以我们取group.width/2:

    var canvas = new fabric.Canvas(document.getElementById('c'));
    
    var rect = new fabric.Rect({
        width: 100,
        height: 100,
        left: 50,
        top: 50,
        fill: 'rgba(255,0,0,0.5)'
    });
    var circle = new fabric.Circle({
        radius: 50,
        left: 150,
        top: 75,
        fill: '#aac'
    });
    
    
    canvas.add(rect);
    canvas.add(circle);
    canvas.renderAll();
    
    function getPOS(){
        var group = canvas.getActiveGroup();
        if (group == null) {
            var pos = rect.left;
        }
        else {
            var pos = rect.group.left + rect.group.width/2 + rect.left;
        }
        alert("Position of rect from left:"+pos);
    }
    

    【讨论】:

      【解决方案4】:

      不得不用另一种方法解决这个问题...... 我必须在 JSON 画布数据中查找图像,所以我的代码是:

      let findItemByType = function(source, type, rX, rY)
      {
          rX = rX ? rX : 0;
          rY = rY ? rY : 0;
          let objs = [];
          source.forEach(function(item){
              if (item.type === type){
                  item.rX = rX + item.left;
                  item.rY = rY + item.top;
                  objs.push(item);
              }
              else {
                  if (item.objects)
                  {
                      item.rX = rX;
                      item.rY = rY;
                      let subresult = findItemByType(item.objects, 
                      type, 
                      item.rX + item.left + item.width / 2, 
                      item.rY + item.top + item.height / 2);
                      if (subresult){
                          objs = objs.concat(subresult);
                      }
                  }   
              }
          });
          return objs;
      }
      let images = findItemByType(canvas.toJSON().objects, "image", 0, 0);
      

      这段代码应该带一个包含所有图像对象的数组,它们应该有 rX 和 rY 属性,它们是图像的相对位置。

      【讨论】:

        【解决方案5】:

        一种不需要判断originX originY属性的方法。

        const groupCenter = rect.group.getPointByOrigin('center', 'center');
        absoluteLeft = rect.left + rect.group.left;
        absoluteTop = rect.top + rect.group.top;

        【讨论】:

          【解决方案6】:

          有一种通用的方法可以计算任何对象在画布上的位置,无论组和来源:

          const position = fabric.util.transformPoint(
            // you can choose point of object (left/center/right, top/center/bottom)
            object.getPointByOrigin('left', 'top'), 
            object.calcTransformMatrix()
          )
          

          【讨论】:

          • 对我不起作用,即使它看起来是最正确的答案。 1.如果我有一个没有组的对象,则结果坐标在 x 和 y 中是值的两倍。 2. 如果我有一个组,它按组大小的一半处理。
          猜你喜欢
          • 2016-10-14
          • 2016-12-21
          • 2019-09-03
          • 1970-01-01
          • 1970-01-01
          • 2019-10-27
          • 1970-01-01
          • 2015-03-23
          • 1970-01-01
          相关资源
          最近更新 更多