Как рассчитывается getBBox () SVGRect? - PullRequest
38 голосов
/ 30 мая 2011

У меня есть элемент g, который содержит один или несколько элементов path.Как я уже упоминал в другом вопросе , я масштабирую и переводю элемент g, вычисляя атрибут transform, чтобы он помещался в сетку в другой части холста.

Расчет выполняется с использованием разницы между двумя прямоугольниками, getBBox() от элемента g и прямоугольником вокруг сетки.

Вот вопрос: после преобразования я обновляю содержимое элемента g и снова вызываю getBBox(), без , удаляя transform.Получающийся прямоугольник, кажется, рассчитывается без учета transform.Я ожидал, что это отразит изменение.Соответствует ли это поведение спецификации SVG?Как получить ограничивающий прямоугольник для преобразованного прямоугольника?

Кстати, это документ HTML 5, работающий в Firefox 4, если это имеет какое-то значение.

Обновление: очевидно, это поведениекажется довольно явно в нарушение спецификации.Из текста здесь, в w3c :

SVGRect getBBox ()

Возвращает ограничивающий прямоугольник в текущем пользовательском пространстве (т. Е.после применения атрибута 'transform', если таковой имеется) к геометрии всех содержащихся графических элементов, исключая эффекты обводки, отсечения, маскирования и фильтрации).Обратите внимание, что getBBox должен возвращать фактическую ограничивающую рамку во время вызова метода, даже если элемент еще не отображен.

Правильно ли я читаю?Если так, то это похоже на ошибки в реализации SVG, которые использует Firefox;У меня не было возможности попробовать что-нибудь другое.Я бы подал отчет об ошибке, если бы кто-то мог указать мне, куда.

Ответы [ 6 ]

19 голосов
/ 07 ноября 2014

Люди часто смущаются из-за различий в поведении getBBox и getBoundingClientRect.

getBBox - это собственный метод элемента SVG в качестве эквивалента для определения смещения / клиентской ширины элемента HTML DOM. Ширина и высота никогда не изменятся, даже если элемент повернут . Его нельзя использовать для HTML DOM Elements.

getBoundingClientRect является общим для элементов HTML и SVG. ограниченный прямоугольник ширина и высота изменится, когда элемент поворачивается или когда сгруппировано больше элементов.

15 голосов
/ 09 июня 2011

Поведение, которое вы видите, является правильным и соответствует спецификации.Преобразование применяется, затем bbox вычисляется в «текущих пользовательских единицах», то есть в текущем пользовательском пространстве.Поэтому, если вы хотите увидеть результат преобразования в элементе, вам нужно взглянуть на bbox родительского узла или аналогичный.Это немного сбивает с толку, но объясняется намного лучше в спецификации SVG Tiny 1.2 для SVGLocatable , которая содержит ряд примеров, поясняющих, что она должна делать.

6 голосов
/ 29 июля 2011

есть как минимум 2 простых, но несколько хакерских способа сделать то, что вы просите ... если есть более хорошие (менее хакерские) способы, я их еще не нашел

ЛЕГКИЙ ХАККИ # 1:а) установить прямоугольник, который соответствует "нетрансформированному" bbox, который возвращает group.getBBox ()б) применить «непримененное преобразование» группы к этому прямоугольникуc) rect.getBBox () теперь должен возвращать bbox, который вы ищете

EASY HACKY # 2: (тестируется только в Chrome)а) используйте element.getBoundingClientRect (), который возвращает достаточно информации, чтобы вы могли создать bbox, который вы ищете

4 голосов
/ 04 июня 2011

Очевидно, getBBox () не принимает во внимание преобразования.

Я могу указать вам здесь, к сожалению, я не смог заставить его работать: http://tech.groups.yahoo.com/group/svg-developers/message/22891

3 голосов
/ 08 декабря 2012

Я сделал вспомогательную функцию, которая возвращает различные метрики элемента svg (также bbox преобразованного элемента).

Код здесь: https://stackoverflow.com/a/13111598/1691517

и полный функциональный пример здесь: http://jsbin.com/acowaq/1

3 голосов
/ 23 декабря 2011

В SVG группах есть неприятная практика - не накапливать все сделанные преобразования. У меня есть свой способ справиться с этой проблемой. Я использую свои собственные атрибуты для хранения текущих данных преобразования, которые я включаю в любое дальнейшее преобразование. Используйте XML-совместимые атрибуты, такие как alttext, value, name .... или просто x и y для хранения накопленного значения в качестве атрибута.

Пример:

<g id="group" x="20" y="100" transform="translate(20, 100)">
<g id="subgroup" alttext="45" transform="rotate(45)">
<line...etc...

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

Пример вращения:

function symbRot(evt) {

  evt.target.ondblclick = function () {

    stopBlur();
    var ptx=symbG.parentNode.lastChild.getAttribute("cx");
    var pty=symbG.parentNode.lastChild.getAttribute("cy");
    var currRot=symbG.getAttributeNS(null, "alttext");

    var rotAng;
    if (currRot == 0) {
      rotAng = 90
    } else if (currRot == 90) {
      rotAng = 180
    } else if (currRot == 180) {
      rotAng = 270
    } else if (currRot == 270) {
      rotAng = 0
    };
    symbG.setAttributeNS(null, "transform", "rotate(" + rotAng + "," + ptx + ", " + pty + ")");
    symbG.setAttributeNS(null, "alttext", rotAng );
  };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...