Как получить отношение холста к объекту, находящемуся в группе?

Обычно позиция объекта относительно холста может быть получена из него атрибутами .left и .top, но они становятся относительно группы, если объект находится в группе выбора/группы. Есть ли способ получить свою позицию относительно холста?

Ответ 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();

Ниже приведены три случая возможного центрирования группы:

  • Происхождение группы, установленной в центр (как в коде выше):

    Как показано на рисунке ниже, rect.left дает нам расстояние слева от объекта из центра группы. rect.group.left дает расстояние от центра группы слева от холста.

    Так расстояние справа от холста = rect.left + rect.group.left (http://jsfiddle.net/uue3hcj6/3/)

    enter image description here

  • Происхождение группы установлено в верхнее/левое (также значение по умолчанию)

    rect.left дает нам расстояние слева от объекта из центра группы. rect.group.left дает расстояние слева от группы слева от холста. Теперь, чтобы вычислить оставшееся расстояние, мы должны добавить половину ширины группы.

    Так расстояние прямой слева от холста = rect.left + rect.group.left + rect.group.width/2 (http://jsfiddle.net/uue3hcj6/6/)

    enter image description here

  • Происхождение группы установлено в нижнее/правое

    rect.left дает нам расстояние слева от объекта из центра группы. rect.group.left дает расстояние справа от группы слева от холста. Теперь, чтобы вычислить общее расстояние, мы должны вычесть половину ширины группы.

    Так расстояние прямой слева от холста = rect.left + rect.group.left - rect.group.width/2 (http://jsfiddle.net/uue3hcj6/7/)

    enter image description here

Примечание. Аналогичные случаи возможны и для объекта.

Ответ 2

Решение состоит в учете ширины группы. 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);
}

Ответ 3

Пришлось решить эту проблему с помощью другого подхода... Мне пришлось найти изображения в данных холста 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, которые являются относительными позициями изображений.