Ограничительная коробка / bbox для группы после вращения в svg. js - PullRequest
2 голосов
/ 11 февраля 2020

Используя svg. js, я нарисовал (игровую) доску, которая по сути представляет собой группу шестиугольных дорожек. После того, как все гексы добавлены, я хотел бы повернуть всю группу на -60 градусов, а затем прочитать минимальную прямоугольную рамку angular, которая включает в себя результирующую (визуальную) форму.

Внешний вид доски и коробку (нарисованную от руки красным), я хочу:

enter image description here

Но я не могу понять, как получить красную коробку; все, что я когда-либо получаю, похоже на прямоугольники вокруг синей фигуры (которая, конечно же, вращается вокруг всей группы, сама вращается):

enter image description here

Некоторые подсказки, которые я нашел, заключались в использовании внешней группы (содержащей в свою очередь группу, которая собирает поля); поверните внутреннюю группу и получите bbox () из внешней группы; к сожалению, это ничего не изменило. В качестве альтернативы, некоторые источники в Интернете предложили вместо этого использовать rbox (), но это опять ничего не изменило, и даже в документации svg. js 3.0.

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

 draw_board() {
        let grp = this.canvas.group();
        for (let field of this.fields) {
            field.hex_display = grp.use(hexsym).size(this.w*this.hex_scale,this.h*this.hex_scale)
                .center(field.cx,field.cy)
                .addClass("hex_field")
                .addClass(this.color);

        }
        let count = this.field.length;
        let clipper = this.canvas.clip().path()
              .M(...this.center(0,0))
              .L(...this.center(0,count-1))
              .L(...this.center(count-1,count-1))
              .L(...this.center(count-1,0))
              .Z();
        grp.clipWith(clipper);
        grp.rotate(-60);
        let bb = grp.bbox();
        this.canvas.viewbox(bb.x,bb.y,bb.w,bb.h)
    }

Любые указатели, как подойти к этому?

Ответы [ 2 ]

1 голос
/ 11 февраля 2020

Вот пример для расширения комментария @RobertLongson. Красный getBoundingClientRect, зеленый getBBox. Я не уверен, что любой из них поможет тебе. Использование getBoundingClientRect потребует определения местоположения svg по отношению к документу, поэтому оно смещено.

var rotate = 0;

function doRotation() {
  rotate += 10;
  if (rotate === 360) {
    rotate = 0;
  }
  var pathElement = document.querySelector('#path_1');
  pathElement.setAttribute('transform', 'rotate(' + rotate + ' 40 40 )');
  var groupElement = document.querySelector('#group_1');
  var rectBBox = document.querySelector('#rect_1');
  var rectBoundingClientRect = document.querySelector('#rect_2');

  var bboxGroup = groupElement.getBBox();
  rectBBox.setAttribute('x', bboxGroup.x);
  rectBBox.setAttribute('y', bboxGroup.y);
  rectBBox.setAttribute('width', bboxGroup.width);
  rectBBox.setAttribute('height', bboxGroup.height);

  var boundingClientRectGroup = groupElement.getBoundingClientRect();
  rectBoundingClientRect.setAttribute('x', boundingClientRectGroup.x);
  rectBoundingClientRect.setAttribute('y', boundingClientRectGroup.y);
  rectBoundingClientRect.setAttribute('width', boundingClientRectGroup.width);
  rectBoundingClientRect.setAttribute('height', boundingClientRectGroup.height);
}
setInterval(doRotation, 100);
svg {
  overflow: visible
}
<svg height="100px" viewBox="0 0 100 100">
  <g  id="group_1">
  <path id="path_1" d="M35,25 L60,25 L50,50 L25,50 Z"></path>
  </g>
  <rect vector-effect="non-scaling-stroke" id="rect_1" stroke="#00ff00" stroke-width="1" fill="none"> </rect> 
  <rect  vector-effect="non-scaling-stroke" id="rect_2" stroke="#ff0000" stroke-width="1" fill="none"></rect> 
</svg>
0 голосов
/ 12 февраля 2020

Используйте rbox. Это так же просто, как grp.rbox(this.canvas)

Rbox, по сути, является оболочкой для getBoundingClientRect. Однако, если вы передадите элемент, блок преобразуется в систему координат этого элемента. В вашем случае вам нужны координаты в системе координат canvas.

Если вы вызовете rbox без параметра, он даст вам окно с координатами экрана с добавленной прокруткой (в отличие от getBoundingClientRect)

Здесь это ссылка на документы: https://svgjs.com/docs/3.0/manipulating/#rbox

...