Подтвердить что ты не робот

Поиск смещения положения элемента SVG

Я столкнулся с этой проблемой много с D3. Много времени мне нравится накладывать HTML-объекты поверх SVG.

Моя текущая стратегия создает пустой DIV рядом с элементом SVG, который называется .html-overlay. Я размещаю его в соответствии с внутренним заполнением, которое я установил в SVG для моей основной графики (например: 20px). Затем я использую следующую функцию (с jQuery), чтобы выяснить, куда должен идти элемент HTML:

//element is the object returned by D3 .append()
var getOffset: function(element) {
        var $element = $(element[0][0]);
        return {
            left: $element.offset().left - $('.html-overlay').offset().left,
            top: $element.offset().top - $('.html-overlay').offset().top
        };
    }

Интересно, что ДОЛЖЕН быть некоторый внутренний (не-jQuery зависимый) способ быстро получить смещение элемента. Это очень полезно (особенно после того, как элементы проходят через множественные переводы, вращения, масштабирование и т.д.)

Было бы здорово иметь функции для вычисления смещения "центра" элемента, самой верхней точки элемента, самой нижней, самой левой, самой правой и т.д.

Примечание:

Функция getBoundingClientRect() по какой-либо причине не дает правильных чисел:

var $element = $(element[0][0]);

            console.log($element.offset(), element[0][0].getBoundingClientRect())
Object
left: 328
top: 248.8333282470703
__proto__: Object

ClientRect
bottom: 376.83331298828125
height: 139.99998474121094
left: 328
right: 478
top: 236.8333282470703
width: 150
4b9b3361

Ответ 1

Вы пробовали

var xywh =element[0][0].getBoundingClientRect();

похоже, все в нем? (оригинал soution находится в этом сообщении)

Ответ 2

Проблема заключается в getBoundingClientRect, который не учитывает позицию прокрутки или позицию контейнера элемента относительно документа. Он будет отчитывать только , что, точное положение относительно верхних и левых координат документа.

Я создал метод d3, который будет возвращать позицию элемента. Он работает путем циклического перемещения по родительским элементам до тех пор, пока не найдет SVG контейнера, а затем рассмотрит позицию позиции в вычислениях. Он возвращает то, что вы обычно получали от getBoundingClientRect.

Здесь метод:

d3.selection.prototype.position = function() {

    var el = this.node();
    var elPos = el.getBoundingClientRect();
    var vpPos = getVpPos(el);

    function getVpPos(el) {
        if(el.parentElement.tagName === 'svg') {
            return el.parentElement.getBoundingClientRect();
        }
        return getVpPos(el.parentElement);
    }

    return {
        top: elPos.top - vpPos.top,
        left: elPos.left - vpPos.left,
        width: elPos.width,
        bottom: elPos.bottom - vpPos.top,
        height: elPos.height,
        right: elPos.right - vpPos.left
    };

};

И вы можете использовать его так:

d3.select(element).position()

Обратите внимание, что я действительно не добавил код здесь, чтобы рассмотреть положение прокрутки.

Ответ 3

Расширение ответа Джеймса Лай для поддержки современных версий IE:

function getVpPos(el) {
    if(el.parentNode.nodeName === 'svg') {
        return el.parentNode.getBoundingClientRect();
    }
    return getVpPos(el.parentNode);
}

Примечание. parentElement изменен на parentNode и tagName изменено на имя узла.