Я только что натолкнулся на странный случай вычисления позиций подпрыгивающей коробки и, похоже, я еще не понял причины этого.
Прежде всего, bounding box определяется как самый близко прилегающий прямоугольник, в который может быть заключен не трансформированный элемент.
У меня всегда было впечатление, что для групп это означает, что в основном это bounding box всех детей группы.
Однако сегодня я наткнулся на это:
<g id="outer">
<g id="inner" transform="translate(100, 100)">
<rect x="0" y="0" width="100" height="100" />
</g>
</g>
bounding boxes (границы) элементов следующие:
rect: x: 0, y: 0, w: 100, h: 100
#inner: x: 0, y: 0, w: 100, h: 100
#outer: x: 100, y: 100, w: 100, h: 100
Я ожидал, что все блоки одинаковы, но, как вы можете видеть, внешний блок НЕ является объединением внутренних элементов (в этом случае он будет равен bbox #inner).
Вместо этого он принимает значение преобразование внутренних элементов.
Итак, правильно ли говорить, что bbox группы является объединением трансформированных bbox ее дочерних элементов?
Или, если говорить более программно, объединение всех вызовов getBoundingClientRect (при условии, что scroll равен 0, так как getBoundingClientRect игнорирует scroll)?
Был бы очень признателен за ссылку, указывающую мне на правильную часть спецификации.
В этой демонстрации красный многоугольник представляет #outer BBox во время анимации, в которой вращается чёрный прямоугольник.
const SVG_NS = 'http://www.w3.org/2000/svg';
let o = outer.getBBox()
let i = inner.getBBox()
let BBpoly = drawBBox(o);
function drawBBox(bb){
let p = [{x:bb.x,y:bb.y},
{x:bb.x+bb.width,y:bb.y},
{x:bb.x+bb.width,y:bb.y+bb.height},
{x:bb.x,y:bb.y+bb.height}];
let BBpoly = drawPolygon(p, BBoxes);
return BBpoly;
}
function drawPolygon(p, parent) {
let poly = document.createElementNS(SVG_NS, 'polygon');
let ry = [];
for (var i = 0; i < p.length; i++) {
ry.push(String(p[i].x + ", " + p[i].y));
}
var points = ry.join(" ");
poly.setAttributeNS(null, 'points', points);
parent.appendChild(poly);
return poly;
}
function updatePolygon(p,poly){
let ry = [];
for (var i = 0; i < p.length; i++) {
ry.push(String(p[i].x + ", " + p[i].y));
}
var points = ry.join(" ");
poly.setAttributeNS(null, 'points', points);
}
let a = 0;
function Frame(){
requestAnimationFrame(Frame);
inner.setAttributeNS(null,"transform", `rotate(${a}, 120,120)`)
let bb = outer.getBBox()
let p = [{x:bb.x,y:bb.y},
{x:bb.x+bb.width,y:bb.y},
{x:bb.x+bb.width,y:bb.y+bb.height},
{x:bb.x,y:bb.y+bb.height}];
updatePolygon(p,BBpoly);
a++
}
Frame()
svg{border:1px solid; width:300px;}
polygon{fill:none; stroke:red; }
<svg viewBox="0 0 250 250">
<g id="BBoxes"></g>
<g id="outer">
<g id="inner">
<rect x="70" y="70" width="100" height="100" />
</g>
</g>
</svg>
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости